www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - linking C++ to D on windows troubles...

reply clayasaurus <clayasaurus gmail.com> writes:
What is the correct way to link a C++ library to D under windows? I can 
get it to work under linux, but on windows I get undefined symbols.

Here's what I've tried so far...


1) Used implib to convert a DLL to a .lib file with the command 'implib 
MyLib.lib MyLib.dll' For some reason, the linker still can't find the 
symbols for the DLL file.

2) in my C++ code, I use

extern "C" {
   func();
}

should I be using extern "Windows" instead? I googled to see if there 
was one but I couldn't find anything about it.

and in my D code I use...

extern(C) or extern(Windows) (i've tried both)
{
   func();
}


I also use dmc to compile my cpp code, and create a lib with 'lib -c 
mylib.lib a.obj b.obj c.obj' For some reason the linker doesn't 
recognize the symbols inside of a.obj and b.obj and c.obj so I just end 
up passing a.obj and b.obj and c.obj directly to the compiler, which 
then recognizes objects and compains about all the ones missing from the 
DLL i'm trying to use.


3) I compile it all with .. build test.d -Lmyimplib.lib -Lmycpplib.lib

Is this not the correct way to link lib files to D? Because it doesn't 
seem to be working for me.

Also, are D's .lib files and ming32's .a files compatible? I get the 
feeling they are not, otherwise I would just use my RakNet.a file 
compiled with ming32.

I guess my main problem is hooking the DLL up to my D application :-/

Thanks
~ Clay
Nov 19 2005
next sibling parent reply "John C" <johnch_atms hotmail.com> writes:
"clayasaurus" <clayasaurus gmail.com> wrote in message 
news:dlo8gc$19vi$1 digitaldaemon.com...
 What is the correct way to link a C++ library to D under windows? I can 
 get it to work under linux, but on windows I get undefined symbols.

 Here's what I've tried so far...


 1) Used implib to convert a DLL to a .lib file with the command 'implib 
 MyLib.lib MyLib.dll' For some reason, the linker still can't find the 
 symbols for the DLL file.

 2) in my C++ code, I use

 extern "C" {
   func();
 }

 should I be using extern "Windows" instead? I googled to see if there was 
 one but I couldn't find anything about it.

 and in my D code I use...

 extern(C) or extern(Windows) (i've tried both)
 {
   func();
 }


 I also use dmc to compile my cpp code, and create a lib with 'lib -c 
 mylib.lib a.obj b.obj c.obj' For some reason the linker doesn't recognize 
 the symbols inside of a.obj and b.obj and c.obj so I just end up passing 
 a.obj and b.obj and c.obj directly to the compiler, which then recognizes 
 objects and compains about all the ones missing from the DLL i'm trying to 
 use.


 3) I compile it all with .. build test.d -Lmyimplib.lib -Lmycpplib.lib

 Is this not the correct way to link lib files to D? Because it doesn't 
 seem to be working for me.

 Also, are D's .lib files and ming32's .a files compatible? I get the 
 feeling they are not, otherwise I would just use my RakNet.a file compiled 
 with ming32.

 I guess my main problem is hooking the DLL up to my D application :-/

 Thanks
 ~ Clay

Sounds like your DLL functions aren't getting exported. You need to use dllexport on functions you wish to export, like this: #ifdef __cplusplus extern "C" { #endif __declspec(dllexport) void func(); #ifdef __cplusplus } #endif
Nov 19 2005
parent reply clayasaurus <clayasaurus gmail.com> writes:
John C wrote:
 "clayasaurus" <clayasaurus gmail.com> wrote in message 
 news:dlo8gc$19vi$1 digitaldaemon.com...
 
What is the correct way to link a C++ library to D under windows? I can 
get it to work under linux, but on windows I get undefined symbols.

Here's what I've tried so far...


1) Used implib to convert a DLL to a .lib file with the command 'implib 
MyLib.lib MyLib.dll' For some reason, the linker still can't find the 
symbols for the DLL file.

2) in my C++ code, I use

extern "C" {
  func();
}

should I be using extern "Windows" instead? I googled to see if there was 
one but I couldn't find anything about it.

and in my D code I use...

extern(C) or extern(Windows) (i've tried both)
{
  func();
}


I also use dmc to compile my cpp code, and create a lib with 'lib -c 
mylib.lib a.obj b.obj c.obj' For some reason the linker doesn't recognize 
the symbols inside of a.obj and b.obj and c.obj so I just end up passing 
a.obj and b.obj and c.obj directly to the compiler, which then recognizes 
objects and compains about all the ones missing from the DLL i'm trying to 
use.


3) I compile it all with .. build test.d -Lmyimplib.lib -Lmycpplib.lib

Is this not the correct way to link lib files to D? Because it doesn't 
seem to be working for me.

Also, are D's .lib files and ming32's .a files compatible? I get the 
feeling they are not, otherwise I would just use my RakNet.a file compiled 
with ming32.

I guess my main problem is hooking the DLL up to my D application :-/

Thanks
~ Clay

Sounds like your DLL functions aren't getting exported. You need to use dllexport on functions you wish to export, like this: #ifdef __cplusplus extern "C" { #endif __declspec(dllexport) void func(); #ifdef __cplusplus } #endif

I mentioned that using the -Lmylib.lib didn't find the symbols for the compiler, but adding each obj seperately with 'a.obj b.obj c.obj' worked. Any idea what could cause this? Thanks.
Nov 19 2005
parent reply clayasaurus <clayasaurus gmail.com> writes:
clayasaurus wrote:
 John C wrote:
 
 "clayasaurus" <clayasaurus gmail.com> wrote in message 
 news:dlo8gc$19vi$1 digitaldaemon.com...

 What is the correct way to link a C++ library to D under windows? I 
 can get it to work under linux, but on windows I get undefined symbols.

 Here's what I've tried so far...


 1) Used implib to convert a DLL to a .lib file with the command 
 'implib MyLib.lib MyLib.dll' For some reason, the linker still can't 
 find the symbols for the DLL file.

 2) in my C++ code, I use

 extern "C" {
  func();
 }

 should I be using extern "Windows" instead? I googled to see if there 
 was one but I couldn't find anything about it.

 and in my D code I use...

 extern(C) or extern(Windows) (i've tried both)
 {
  func();
 }


 I also use dmc to compile my cpp code, and create a lib with 'lib -c 
 mylib.lib a.obj b.obj c.obj' For some reason the linker doesn't 
 recognize the symbols inside of a.obj and b.obj and c.obj so I just 
 end up passing a.obj and b.obj and c.obj directly to the compiler, 
 which then recognizes objects and compains about all the ones missing 
 from the DLL i'm trying to use.


 3) I compile it all with .. build test.d -Lmyimplib.lib -Lmycpplib.lib

 Is this not the correct way to link lib files to D? Because it 
 doesn't seem to be working for me.

 Also, are D's .lib files and ming32's .a files compatible? I get the 
 feeling they are not, otherwise I would just use my RakNet.a file 
 compiled with ming32.

 I guess my main problem is hooking the DLL up to my D application :-/

 Thanks
 ~ Clay

Sounds like your DLL functions aren't getting exported. You need to use dllexport on functions you wish to export, like this: #ifdef __cplusplus extern "C" { #endif __declspec(dllexport) void func(); #ifdef __cplusplus } #endif

I mentioned that using the -Lmylib.lib didn't find the symbols for the compiler, but adding each obj seperately with 'a.obj b.obj c.obj' worked. Any idea what could cause this? Thanks.

Forgot to mention, I found a static lib that I could use instead of a DLL. However, if I can't get my own static libs to work then I'm stuck.
Nov 19 2005
parent reply clayasaurus <clayasaurus gmail.com> writes:
C:\CINTER~1>build chat.d -g -Rn -full -cleanup -debug -Lrakglue.lib 
-LRakNetLibStatic.lib
C:\dmd\bin\..\..\dm\bin\link.exe 
chat+raknet\server+raknet\raknet+raknet\client+raknet\packetenumerations+raknet\packetpriority+raknet\networktypes,chat.exe,,user32+kernel32,chat.def/co/noirakglue.libRakNetLibStatic.lib;

OPTLINK (R) for Win32  Release 7.50B1
Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved

OPTLINK : Warning 9: Unknown Option : NOIRAKGLUE.LIBRAKNETLIBSTATIC.LIB
C:\dmd\bin\..\lib\phobos.lib(ti_double)  Offset 19FC5H Record Type 0091
  Error 1: Previous Definition Different : __init_10TypeInfo_d
C:\dmd\bin\..\lib\phobos.lib(ti_double)  Offset 19FDFH Record Type 0091
  Error 1: Previous Definition Different : __Class_10TypeInfo_d
C:\dmd\bin\..\lib\phobos.lib(ti_double)  Offset 19FF8H Record Type 0091
  Error 1: Previous Definition Different : __vtbl_10TypeInfo_d
chat.obj(chat)
  Error 42: Symbol Undefined _rakClientInterface_REG_AS_RPC 8
chat.obj(chat)
  etc. list of undefined symbols...

:-/ It works if I just use the .obj files, but I need it to work with .lib

clayasaurus wrote:
 clayasaurus wrote:
 
 John C wrote:

 "clayasaurus" <clayasaurus gmail.com> wrote in message 
 news:dlo8gc$19vi$1 digitaldaemon.com...

 What is the correct way to link a C++ library to D under windows? I 
 can get it to work under linux, but on windows I get undefined symbols.

 Here's what I've tried so far...


 1) Used implib to convert a DLL to a .lib file with the command 
 'implib MyLib.lib MyLib.dll' For some reason, the linker still can't 
 find the symbols for the DLL file.

 2) in my C++ code, I use

 extern "C" {
  func();
 }

 should I be using extern "Windows" instead? I googled to see if 
 there was one but I couldn't find anything about it.

 and in my D code I use...

 extern(C) or extern(Windows) (i've tried both)
 {
  func();
 }


 I also use dmc to compile my cpp code, and create a lib with 'lib -c 
 mylib.lib a.obj b.obj c.obj' For some reason the linker doesn't 
 recognize the symbols inside of a.obj and b.obj and c.obj so I just 
 end up passing a.obj and b.obj and c.obj directly to the compiler, 
 which then recognizes objects and compains about all the ones 
 missing from the DLL i'm trying to use.


 3) I compile it all with .. build test.d -Lmyimplib.lib -Lmycpplib.lib

 Is this not the correct way to link lib files to D? Because it 
 doesn't seem to be working for me.

 Also, are D's .lib files and ming32's .a files compatible? I get the 
 feeling they are not, otherwise I would just use my RakNet.a file 
 compiled with ming32.

 I guess my main problem is hooking the DLL up to my D application :-/

 Thanks
 ~ Clay

Sounds like your DLL functions aren't getting exported. You need to use dllexport on functions you wish to export, like this: #ifdef __cplusplus extern "C" { #endif __declspec(dllexport) void func(); #ifdef __cplusplus } #endif

I mentioned that using the -Lmylib.lib didn't find the symbols for the compiler, but adding each obj seperately with 'a.obj b.obj c.obj' worked. Any idea what could cause this? Thanks.

Forgot to mention, I found a static lib that I could use instead of a DLL. However, if I can't get my own static libs to work then I'm stuck.

Nov 19 2005
next sibling parent reply John Reimer <terminal.node gmail.com> writes:
clayasaurus wrote:
 C:\CINTER~1>build chat.d -g -Rn -full -cleanup -debug -Lrakglue.lib 
 -LRakNetLibStatic.lib
 C:\dmd\bin\..\..\dm\bin\link.exe 
 chat+raknet\server+raknet\raknet+raknet\client+raknet\packetenumerations+raknet\packetpriority+raknet\networktypes,chat.exe,,user32+kernel32,chat.def/co/noirakglue.lib
akNetLibStatic.lib; 
 
 
 OPTLINK (R) for Win32  Release 7.50B1
 Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved
 

Why is buiild giving this warning:
 OPTLINK : Warning 9: Unknown Option : NOIRAKGLUE.LIBRAKNETLIBSTATIC.LIB

For some reason, the build command line is being processed incorrectly by optlink. Why are you using -L switch on the command line? It appears that the -L flag passes its contents on to optlink via dmd. In this case -L is supposed to accept "linker flags", not a library name (unless I'm mistaken). Why don't you just include the library name without the switch decorating it? Like so: c:\CINTER~1>build chat.d -g -Rn -full -cleanup -debug rakglue.lib
 C:\dmd\bin\..\lib\phobos.lib(ti_double)  Offset 19FC5H Record Type 0091
  Error 1: Previous Definition Different : __init_10TypeInfo_d
 C:\dmd\bin\..\lib\phobos.lib(ti_double)  Offset 19FDFH Record Type 0091
  Error 1: Previous Definition Different : __Class_10TypeInfo_d
 C:\dmd\bin\..\lib\phobos.lib(ti_double)  Offset 19FF8H Record Type 0091
  Error 1: Previous Definition Different : __vtbl_10TypeInfo_d
 chat.obj(chat)
  Error 42: Symbol Undefined _rakClientInterface_REG_AS_RPC 8
 chat.obj(chat)
  etc. list of undefined symbols...
 
 :-/ It works if I just use the .obj files, but I need it to work with .lib

The above should disappear as soon as the *.lib files are correctly submitted to the link command line. It should work just like the object files. It's that nasty -L switch that seems to messing you up. -JJR
Nov 20 2005
parent reply John Reimer <terminal.node gmail.com> writes:
John Reimer wrote:

 Like so:
 
 c:\CINTER~1>build chat.d -g -Rn -full -cleanup -debug rakglue.lib
 

Of course I meant: C:\CINTER~1>build chat.d -g -Rn -full -cleanup -debug rakglue.lib RakNetLibStatic.lib
Nov 20 2005
parent clayasaurus <clayasaurus gmail.com> writes:
John Reimer wrote:
 John Reimer wrote:
 
 Like so:

 c:\CINTER~1>build chat.d -g -Rn -full -cleanup -debug rakglue.lib

Of course I meant: C:\CINTER~1>build chat.d -g -Rn -full -cleanup -debug rakglue.lib RakNetLibStatic.lib

Ahh thanks. I'm used to using the -Llib command because that is how it works under linux. I also realized that my static raknet lib is in the wrong format (coff i think), and raknet doesn't support the dmc compiler (I put a request in their forum), so I'm back to using implib on RakNet.dll. There is also something funky with the librarian, because when I link with the rakglue.lib it says one of my symbols is undefined, however when I link with *.obj it doesn't complain, but then then proceeds to tell me it can't find all the symbols it needs from my implib RakNet.lib file. I know my problems could be fixed if... 1) RakNet supported DMC compiler, so I could create RakNet.lib in DMC's format 2) Pay $15 for coff2omf which may or may not work 3) A native version of GDC on windows so I can use GCC's linker, cygwin won't work because I need access to windows stuff as cygwin doesn't define version(Windows) and it causes problems with import std.c.windows.windows assertion failure. 4) either I'm using implib wrong (implib RakNet.lib RakNet.dll, tried with /s command as well) or something is amiss with the linker. Either way, I'm not getting the symbols from RakNet needed in order to use it. On a final note, error messages I'm getting... C:\CINTER~1>build chat.d -g -Rn -full -cleanup -debug RakNet.lib *.obj C:\dmd\bin\..\..\dm\bin\link.exe *+chat+raknet\server+raknet\raknet+raknet\client+raknet\packetenumerations+raknet\packetpriority+raknet\networktypes,chat.exe,,RakNet.lib+user32+kernel32,chat.def/co/noi; OPTLINK (R) for Win32 Release 7.50B1 Copyright (C) Digital Mars 1989 - 2001 All Rights Reserved rakclient.obj(rakclient) Offset 000D9H Record Type 0091 Error 1: Previous Definition Different : ?UNASSIGNED_PLAYER_ID 3UPlayerID B (const PlayerID UNASSIGNED_PLAYER_ID) rakserver.obj(rakserver) Offset 000D9H Record Type 0091 Error 1: Previous Definition Different : ?UNASSIGNED_PLAYER_ID 3UPlayerID B (const PlayerID UNASSIGNED_PLAYER_ID) rakbitstream.obj(rakbitstream) Error 42: Symbol Undefined ?Read BitStream RakNet QAE_NPAD_OH Z rakbitstream.obj(rakbitstream) Error 42: Symbol Undefined ?Read BitStream RakNet QAE_NAAN Z rakbitstream.obj(rakbitstream) Error 42: Symbol Undefined ?Read BitStream RakNet QAE_NAAM Z rakbitstream.obj(rakbitstream) Error 42: Symbol Undefined ?Read BitStream RakNet QAE_NAAH Z rakbitstream.obj(rakbitstream) Error 42: Symbol Undefined ?Read BitStream RakNet QAE_NAAI Z rakbitstream.obj(rakbitstream) Error 42: Symbol Undefined ?Read BitStream RakNet QAE_NAAF Z rakbitstream.obj(rakbitstream) Error 42: Symbol Undefined ?Read BitStream RakNet QAE_NAAG Z rakbitstream.obj(rakbitstream) etc. etc. Kudos to anyone who can figure out what is wrong. I'm starting to give up on the windows port. Anyways, thanks to JC, JR, Derek, and anyone else who has time enough to read this : ) ~ Clay
Nov 20 2005
prev sibling parent Derek Parnell <derek psych.ward> writes:
On Sun, 20 Nov 2005 01:46:28 -0500, clayasaurus wrote:

 C:\CINTER~1>build chat.d -g -Rn -full -cleanup -debug -Lrakglue.lib 

[snip]
 I mentioned that using the -Lmylib.lib didn't find the symbols for the 
 compiler, but adding each obj seperately with 'a.obj b.obj c.obj' 
 worked. Any idea what could cause this?



The -L switch is used to pass 'flags' to the linker and not library names. I assume that because you are on Windows that this is using optlink as the linker. The only way to pass library names to optlink is by placing them on the command line as plain file names, because optlink does not accept library names as flags/switches. Instead optlink only accepts library names as positional command line parameters, and dmd formats the command line for optlink. (By the way, the next Build will allow an alternative to this, however I've only coded the Windows edition so far and the linux stuff is still work-in-progress). -- Derek Parnell Melbourne, Australia 21/11/2005 6:34:34 AM
Nov 20 2005
prev sibling parent "Walter Bright" <newshound digitalmars.com> writes:
I recommend taking this sample code:

extern (D) int food(char c, int x)
{
    return c / x;
}

extern (C) int fooc(char c, int x)
{
    return c / x;
}

extern (C++) int foocpp(char c, int x)
{
    return c / x;
}

extern (Windows) int foow(char c, int x)
{
    return c / x;
}

and compile it. Run obj2asm on the resulting obj file. Then you'll see the
different name mangling schemes, and the different calling conventions.

The linker doesn't know anything about function calling conventions. Nada,
zip. It only deals with the mangled name, and tries to match the mangled
name identifier strings. If they don't match, it won't link.

Therefore, if things don't link due to "undefined symbols", and it's a
mystery why, then:

1) obj2asm the .obj file that you assume should define the symbol.
2) obj2asm the .obj file that you assume should reference the symbol.

Compare the names. If they don't match, or are missing, you have a good
starting point to figure out where things went wrong.
Nov 24 2005