## digitalmars.D.learn - Linking C libraries with DMD

• jmh530 (24/24) Jan 21 I'm trying to understand calling C libraries from D on Windows
• W.J. (8/32) Jan 21 You need to port the header file to d. i believe there's the htod
• Andrea Fontana (6/8) Jan 21 You should try with dstep too.
• W.J. (3/11) Jan 21 Interesting read. Thanks for sharing!
• jmh530 (12/19) Jan 21 I already ported the header file to d. What I can't get to work
• Dibyendu Majumdar (15/22) Jan 21 Hi I am also new to D and trying to do similar things - i.e. call
• jmh530 (5/19) Jan 21 I'm not having any luck using your options with dmd either
• Dibyendu Majumdar (5/14) Jan 21 Sorry forgot to mention that I also include the library I am
• jmh530 (8/23) Jan 21 The -L/LIBPATH:c:\lib gives me an error that
• Dibyendu Majumdar (4/10) Jan 21 OPTLINK is for 32-bit code - the options I showed are for 64-bit,
• jmh530 (15/26) Jan 21 Thanks. I had been trying to get 32bit code to work. I don't
• Dibyendu Majumdar (7/20) Jan 21 Sorry the option should be -L/IMPLIB:.. - with single slash but
• jmh530 (15/21) Jan 21 The single slash didn't make a difference. I tried that myself
• jmh530 (2/2) Jan 21 I also added an enhancement request:
• Dibyendu Majumdar (15/26) Jan 21 Okay then you don't need the /IMPLIB option. But you do need to
• jmh530 (10/39) Jan 21 I ran
• W.J. (22/70) Jan 21 The linker will most certainly get confused by this "-L
• jmh530 (5/20) Jan 21 The -L-L stuff from the LearningD book is making more sense. The
• bachmeier (8/16) Jan 21 Have you used pragma(lib)? https://dlang.org/spec/pragma.html#lib
• jmh530 (44/52) Jan 21 Looks like the sections are split apart by a couple hundred
• bachmeier (7/44) Jan 21 That should be implib /system libclib.lib libclib.dll. I'm pretty
• Mike Parker (51/58) Jan 21 Your confusion appears to be coming from a lack of understanding
• jmh530 (2/3) Jan 21 Thanks for the detailed reply.
• Mike Parker (55/71) Jan 21 I've take your example, modified it slightly, compiled the DLL
• jmh530 (2/3) Jan 22 Thanks again! Will review.
• jmh530 (17/18) Feb 02 Thanks again for your help. I've worked through some simple
• jmh530 (5/7) Feb 02 Yeah, this is what finally allowed me to progress.
jmh530 <john.michael.hall gmail.com> writes:
I'm trying to understand calling C libraries from D on Windows
with DMD. I made a simple example and compiled it with a static
library fine (so I've converted the .h file correctly). Then, I
compiled with gcc to a shared library (because I cannot for the
life of me figure out how to do this with DMC). I then used
implib to generate a .lib file (the fact that this is necessary
is not described nearly well enough in the documentation).

The next step is getting this to compile with dmd. I'm getting an
error that the function isn't getting called, which is suggesting
that I'm not linking the .lib file with DMD properly.

The dmd page
https://dlang.org/dmd-windows.html
explains that -L is used to pass stuff to the linker. It seems to
indicate that this should be the folder that the library is in.
The dll and lib files are in the same folder as the .d file I'm
trying to compile. So presumably, this should be -L. or -L\. or
like -LC:\folder\. But nothing like that works. There's a link on
the dmd page to optlink, which doesn't really help me figure this
out either. There's also some stuff about set LIB in the sci.ini.
Not sure I'm supposed to mess with that.

The LearningD book has some examples as well. I don't have it in
front of me right now, but I think I tried what they recommend
also. Nevertheless, I feel like the documentation should be clear
enough so that this isn't so frustrating.

Jan 21
W.J. <invalid email.address> writes:
On Thursday, 21 January 2016 at 16:14:40 UTC, jmh530 wrote:
I'm trying to understand calling C libraries from D on Windows
with DMD. I made a simple example and compiled it with a static
library fine (so I've converted the .h file correctly). Then, I
compiled with gcc to a shared library (because I cannot for the
life of me figure out how to do this with DMC). I then used
implib to generate a .lib file (the fact that this is necessary
is not described nearly well enough in the documentation).

The next step is getting this to compile with dmd. I'm getting
an error that the function isn't getting called, which is
suggesting that I'm not linking the .lib file with DMD properly.

The dmd page
https://dlang.org/dmd-windows.html
explains that -L is used to pass stuff to the linker. It seems
to indicate that this should be the folder that the library is
in. The dll and lib files are in the same folder as the .d file
I'm trying to compile. So presumably, this should be -L. or
-L\. or like -LC:\folder\. But nothing like that works. There's
a link on the dmd page to optlink, which doesn't really help me
figure this out either. There's also some stuff about set LIB
in the sci.ini. Not sure I'm supposed to mess with that.

The LearningD book has some examples as well. I don't have it
in front of me right now, but I think I tried what they
recommend also. Nevertheless, I feel like the documentation
should be clear enough so that this isn't so frustrating.

You need to port the header file to d. i believe there's the htod
utility, however I haven't used that yet.
Then, basically all you have to do is to tell the linker to link
against your C .lib.
Remember that -LC:\folder (for dmd) passes "C:\folder" on to the
linker. Assuming the library folder flag for your linker is -L,
you'd want to use -L-LC:\folder.

Jan 21
Andrea Fontana <nospam example.com> writes:
On Thursday, 21 January 2016 at 16:57:26 UTC, W.J. wrote:
You need to port the header file to d. i believe there's the
htod utility, however I haven't used that yet.

You should try with dstep too.

http://wiki.dlang.org/List_of_Bindings

And here:
http://wiki.dlang.org/D_binding_for_C

Jan 21
W.J. <invalid email.address> writes:
On Thursday, 21 January 2016 at 17:00:14 UTC, Andrea Fontana
wrote:
On Thursday, 21 January 2016 at 16:57:26 UTC, W.J. wrote:
You need to port the header file to d. i believe there's the
htod utility, however I haven't used that yet.

You should try with dstep too.

http://wiki.dlang.org/List_of_Bindings

And here:
http://wiki.dlang.org/D_binding_for_C

Interesting read. Thanks for sharing!

Jan 21
jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 21 January 2016 at 16:57:26 UTC, W.J. wrote:
You need to port the header file to d. i believe there's the
htod utility, however I haven't used that yet.
Then, basically all you have to do is to tell the linker to
Remember that -LC:\folder (for dmd) passes "C:\folder" on to
the linker. Assuming the library folder flag for your linker is
-L, you'd want to use -L-LC:\folder.

I already ported the header file to d. What I can't get to work
is linking a dynamic library.

The whole -L-L is definitely not intuitive. The optlink
documentation doesn't even describe a -L option. Anyway, it
doesn't give an error when I use a plus so I tried
dmd <file.d> -L-L+C:\folder\
and it still isn't picking it up. I figured I needed to tell the
linker what the file actually is, so I tried
dmd <file.d> -L-L+C:\folder\ -L-lib+<libfile.lib>
and that (and a variety of variations) gives errors that LIB
isn't recognized.

Jan 21
Dibyendu Majumdar <d.majumdar gmail.com> writes:
On Thursday, 21 January 2016 at 16:14:40 UTC, jmh530 wrote:
I'm trying to understand calling C libraries from D on Windows
with DMD. I made a simple example and compiled it with a static
library fine (so I've converted the .h file correctly). Then, I
compiled with gcc to a shared library (because I cannot for the
life of me figure out how to do this with DMC). I then used
implib to generate a .lib file (the fact that this is necessary
is not described nearly well enough in the documentation).

Hi I am also new to D and trying to do similar things - i.e. call
a shared library written in C from D, but also create a shared
library in D.

For the latter - on Windows 10 b64-bit - I am using following
options for example:

-shared -L/LIBPATH:c:\\lib  -L//IMPLIB:mylib.lib

In my case I would like stuff from my D code to be exported. I
found that I need to do following if I want to export a C API.

extern (C) export void myfunc();

I did not find examples of how to export D classes / functions -
and right now I am getting link errors when trying to export D
code.

Regards
Dibyendu

Jan 21
jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 21 January 2016 at 21:39:08 UTC, Dibyendu Majumdar
wrote:
Hi I am also new to D and trying to do similar things - i.e.
call a shared library written in C from D, but also create a
shared library in D.

For the latter - on Windows 10 b64-bit - I am using following
options for example:

-shared -L/LIBPATH:c:\\lib  -L//IMPLIB:mylib.lib

In my case I would like stuff from my D code to be exported. I
found that I need to do following if I want to export a C API.

extern (C) export void myfunc();

I did not find examples of how to export D classes / functions
- and right now I am getting link errors when trying to export
D code.

Regards
Dibyendu

I'm not having any luck using your options with dmd either
(excluding -shared because I don't need to create a shared D
library).

Jan 21
Dibyendu Majumdar <d.majumdar gmail.com> writes:
On Thursday, 21 January 2016 at 21:55:10 UTC, jmh530 wrote:
For the latter - on Windows 10 b64-bit - I am using following
options for example:

-shared -L/LIBPATH:c:\\lib  -L//IMPLIB:mylib.lib

I'm not having any luck using your options with dmd either
(excluding -shared because I don't need to create a shared D
library).

Sorry forgot to mention that I also include the library I am

dmd -m64 prog.d -L/LIBPATH:c:\lib -Lyourlib.lib

Where yourlib.lib and yourlib.dll are in c:\lib folder.

Jan 21
jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 21 January 2016 at 22:02:57 UTC, Dibyendu Majumdar
wrote:
On Thursday, 21 January 2016 at 21:55:10 UTC, jmh530 wrote:
For the latter - on Windows 10 b64-bit - I am using following
options for example:

-shared -L/LIBPATH:c:\\lib  -L//IMPLIB:mylib.lib

I'm not having any luck using your options with dmd either
(excluding -shared because I don't need to create a shared D
library).

Sorry forgot to mention that I also include the library I am

dmd -m64 prog.d -L/LIBPATH:c:\lib -Lyourlib.lib

Where yourlib.lib and yourlib.dll are in c:\lib folder.

The -L/LIBPATH:c:\lib gives me an error that
OPTLINK : Warning 9: Unknown Option : LIBPATH
and then gives the path I put is not found.

At least when it's outputting the text, it's combining
:C:\lib\yourlib.lib
so it seemingly is finding it.

Jan 21
Dibyendu Majumdar <d.majumdar gmail.com> writes:
On Thursday, 21 January 2016 at 22:09:47 UTC, jmh530 wrote:
The -L/LIBPATH:c:\lib gives me an error that
OPTLINK : Warning 9: Unknown Option : LIBPATH
and then gives the path I put is not found.

At least when it's outputting the text, it's combining
:C:\lib\yourlib.lib
so it seemingly is finding it.

OPTLINK is for 32-bit code - the options I showed are for 64-bit,
which uses MS LINK. You get 64-bit code by adding -m64.

Regards

Jan 21
jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 21 January 2016 at 22:14:25 UTC, Dibyendu Majumdar
wrote:
On Thursday, 21 January 2016 at 22:09:47 UTC, jmh530 wrote:
The -L/LIBPATH:c:\lib gives me an error that
OPTLINK : Warning 9: Unknown Option : LIBPATH
and then gives the path I put is not found.

At least when it's outputting the text, it's combining
:C:\lib\yourlib.lib
so it seemingly is finding it.

OPTLINK is for 32-bit code - the options I showed are for
64-bit, which uses MS LINK. You get 64-bit code by adding -m64.

Regards

Thanks. I had been trying to get 32bit code to work. I don't
think I did anything special with gcc to compile the dll as
64bit. Anyway, this is what I get when I try it again (stuff in
brackets I replaced).

C:<folder>>dmd -m64 <file>.d -L/LIBPATH:C:<folder>
-L//IMPLIB:<libfile>.lib
LINK : warning LNK4044: unrecognized option
'//IMPLIB:<libfile>.lib'; ignored
callC0.obj : error LNK2019: unresolved external symbol
<cfunction> referenced in f
unction _Dmain
callC0.exe : fatal error LNK1120: 1 unresolved externals
--- errorlevel 1120

Jan 21
Dibyendu Majumdar <d.majumdar gmail.com> writes:
On Thursday, 21 January 2016 at 22:23:36 UTC, jmh530 wrote:
Thanks. I had been trying to get 32bit code to work. I don't
think I did anything special with gcc to compile the dll as
64bit. Anyway, this is what I get when I try it again (stuff in
brackets I replaced).

C:<folder>>dmd -m64 <file>.d -L/LIBPATH:C:<folder>
-L//IMPLIB:<libfile>.lib
LINK : warning LNK4044: unrecognized option
'//IMPLIB:<libfile>.lib'; ignored
callC0.obj : error LNK2019: unresolved external symbol
<cfunction> referenced in f
unction _Dmain
callC0.exe : fatal error LNK1120: 1 unresolved externals
--- errorlevel 1120

Sorry the option should be -L/IMPLIB:.. - with single slash but
you only need this if you are trying to create a shared library
which presumably you are not?

I believe to create a static library you need to use -lib, else
it is an app so you need to supply a main function.

Regards

Jan 21
jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 21 January 2016 at 22:35:29 UTC, Dibyendu Majumdar
wrote:
Sorry the option should be -L/IMPLIB:.. - with single slash but
you only need this if you are trying to create a shared library
which presumably you are not?

I believe to create a static library you need to use -lib, else
it is an app so you need to supply a main function.

Regards

The single slash didn't make a difference. I tried that myself
before posting. I got the same error.

I'm not trying to created a shared library in D. My goal is to
use a shared library from C in D. Right now, I'm working with a
simple test case to make sure I could understand it before
working with the actual shared library I want to use.

I recall some discussion in LearningD (don't have it in front of
me now) that different types of shared libraries are needed on
32bit vs. 64bit because there is a different linker. This is what
I did to created the shared library:

gcc -Wall -fPIC -c <file>.c -I.
gcc -shared -o <libfile>.dll <file>.o -I.
implib <libfile>.lib <libfile>.dll

Jan 21
jmh530 <john.michael.hall gmail.com> writes:
I also added an enhancement request:
https://issues.dlang.org/show_bug.cgi?id=15588

Jan 21
Dibyendu Majumdar <d.majumdar gmail.com> writes:
On Thursday, 21 January 2016 at 22:49:06 UTC, jmh530 wrote:
I'm not trying to created a shared library in D. My goal is to
use a shared library from C in D. Right now, I'm working with a
simple test case to make sure I could understand it before
working with the actual shared library I want to use.

I recall some discussion in LearningD (don't have it in front
of me now) that different types of shared libraries are needed
on 32bit vs. 64bit because there is a different linker. This is
what I did to created the shared library:

gcc -Wall -fPIC -c <file>.c -I.
gcc -shared -o <libfile>.dll <file>.o -I.
implib <libfile>.lib <libfile>.dll

Okay then you don't need the /IMPLIB option. But you do need to
specify the library via -L as I mentioned before.

i.e. use:

dmd -m64 -L/LIBPATH:<path to lib> -L<library name> prog.d

Where <library name> is yourlib.lib and this is present along
with the DLL in the path you gave.

Plus your prog.d needs to have appropriate code. Example:

module app;

extern (C) void testing();

void main()
{
testing();
}

Here testing() is provided in the DLL.

Jan 21
jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 21 January 2016 at 22:54:26 UTC, Dibyendu Majumdar
wrote:
On Thursday, 21 January 2016 at 22:49:06 UTC, jmh530 wrote:
I'm not trying to created a shared library in D. My goal is to
use a shared library from C in D. Right now, I'm working with
a simple test case to make sure I could understand it before
working with the actual shared library I want to use.

I recall some discussion in LearningD (don't have it in front
of me now) that different types of shared libraries are needed
on 32bit vs. 64bit because there is a different linker. This
is what I did to created the shared library:

gcc -Wall -fPIC -c <file>.c -I.
gcc -shared -o <libfile>.dll <file>.o -I.
implib <libfile>.lib <libfile>.dll

Okay then you don't need the /IMPLIB option. But you do need to
specify the library via -L as I mentioned before.

i.e. use:

dmd -m64 -L/LIBPATH:<path to lib> -L<library name> prog.d

Where <library name> is yourlib.lib and this is present along
with the DLL in the path you gave.

Plus your prog.d needs to have appropriate code. Example:

module app;

extern (C) void testing();

void main()
{
testing();
}

Here testing() is provided in the DLL.

I ran

dmd -m64 <file>.d -L/LIBPATH:<path to lib> -L<library name>

and got

<library name> : fatal error LNK1136: invalid or corrupt file
--- errorlevel 1136

At least that's progress.

LNK1136 is for a corrupt or abnormally small file. I did notice
that the original dll was 82kb and the lib file was 2kb.

Jan 21
W.J. <invalid email.address> writes:
On Thursday, 21 January 2016 at 23:07:06 UTC, jmh530 wrote:
On Thursday, 21 January 2016 at 22:54:26 UTC, Dibyendu Majumdar
wrote:
On Thursday, 21 January 2016 at 22:49:06 UTC, jmh530 wrote:
I'm not trying to created a shared library in D. My goal is
to use a shared library from C in D. Right now, I'm working
with a simple test case to make sure I could understand it
before working with the actual shared library I want to use.

I recall some discussion in LearningD (don't have it in front
of me now) that different types of shared libraries are
needed on 32bit vs. 64bit because there is a different
linker. This is what I did to created the shared library:

gcc -Wall -fPIC -c <file>.c -I.
gcc -shared -o <libfile>.dll <file>.o -I.
implib <libfile>.lib <libfile>.dll

Okay then you don't need the /IMPLIB option. But you do need
to specify the library via -L as I mentioned before.

i.e. use:

dmd -m64 -L/LIBPATH:<path to lib> -L<library name> prog.d

Where <library name> is yourlib.lib and this is present along
with the DLL in the path you gave.

Plus your prog.d needs to have appropriate code. Example:

module app;

extern (C) void testing();

void main()
{
testing();
}

Here testing() is provided in the DLL.

I ran

dmd -m64 <file>.d -L/LIBPATH:<path to lib> -L<library name>

and got

<library name> : fatal error LNK1136: invalid or corrupt file
--- errorlevel 1136

At least that's progress.

The linker will most certainly get confused by  this "-L<library
name>" - as it will take it for an object file. The difference is
that a library is a collection of object files.

The GNU linker ld, for instance, uses the -l<libname> switch for
adding libraries to link against and -L<path> to add a search
path to look for the libraries passed in with -l<libname>.

If you leave it to the compiler to invoke the linker you need to
remember the -L compiler switch is passing what follows to the
linker (minus the -L compiler switch).
I.e. -L-LC:\lib\path will be passed on as "-LC:\lib\path",
-L-lsomelib => "-lsomelib", etc.

You won't find help about linker options on any compiler manual.
You have to refer to your linker manual.

Also make sure to adhere to naming conventions. It could very
well be your linker quits with an error message if you pass it
-lsomelib for a file somelib.lib when it expects to find the file

LNK1136 is for a corrupt or abnormally small file. I did notice
that the original dll was 82kb and the lib file was 2kb.

The lib for a 'DLL' is small because it just tells the linker
where to find the code in the 'DLL' - the actual code is in the
'DLL'.

Hope the helps

Jan 21
jmh530 <john.michael.hall gmail.com> writes:
On Friday, 22 January 2016 at 00:43:05 UTC, W.J. wrote:
The GNU linker ld, for instance, uses the -l<libname> switch
for adding libraries to link against and -L<path> to add a
search path to look for the libraries passed in with
-l<libname>.

If you leave it to the compiler to invoke the linker you need
to remember the -L compiler switch is passing what follows to
the linker (minus the -L compiler switch).
I.e. -L-LC:\lib\path will be passed on as "-LC:\lib\path",
-L-lsomelib => "-lsomelib", etc.

The -L-L stuff from the LearningD book is making more sense. The
book is using Linux examples, linux uses ld, which has those
flags.

LNK1136 is for a corrupt or abnormally small file. I did
notice that the original dll was 82kb and the lib file was 2kb.

The lib for a 'DLL' is small because it just tells the linker
where to find the code in the 'DLL' - the actual code is in the
'DLL'.

Hope the helps

That's clear. Thanks.

Jan 21
bachmeier <no spam.net> writes:
On Thursday, 21 January 2016 at 23:07:06 UTC, jmh530 wrote:
I ran

dmd -m64 <file>.d -L/LIBPATH:<path to lib> -L<library name>

and got

<library name> : fatal error LNK1136: invalid or corrupt file
--- errorlevel 1136

At least that's progress.

LNK1136 is for a corrupt or abnormally small file. I did notice
that the original dll was 82kb and the lib file was 2kb.

Have you used pragma(lib)? https://dlang.org/spec/pragma.html#lib
There's also a section on it in Learning D.

I don't use Windows much, but when I link to a dll, that's what I
do. I've actually never used -L options on Windows. If I want to
call functions from R.dll, I use implib /system R.lib R.dll to
create R.lib. Then I put pragma(lib, "R.lib"); in my .d file and
compile.

Jan 21
jmh530 <john.michael.hall gmail.com> writes:
On Friday, 22 January 2016 at 01:34:00 UTC, bachmeier wrote:
Have you used pragma(lib)?
https://dlang.org/spec/pragma.html#lib
There's also a section on it in Learning D.

Looks like the sections are split apart by a couple hundred
pages. I tried it with the .lib I created earlier without much
luck. Also note that the LearningD section recommends not using
the pragma. At this point, I'd rather just having something
working.

I don't use Windows much, but when I link to a dll, that's what
I do. I've actually never used -L options on Windows. If I want
to call functions from R.dll, I use implib /system R.lib R.dll
to create R.lib. Then I put pragma(lib, "R.lib"); in my .d file
and compile.

Thanks for walking through what you do.

I tried to create an example that more closely resembles what is
in LearningD (see
https://github.com/aldacron/LearningD/tree/master/Chapter09_Connecting%2
D%20with%20C/clib). I created two files

clib.c
----------------
#include <stdio.h>

int some_c_function(int);

int some_c_function(int a) {
printf("Hello, D! from C! %d\n", a);
return a + 20;
}

and

dclib.d
-----------------
pragma(lib, libclib.lib);

extern(C)  nogc nothrow {
int some_c_function(int);
}

void main()
{
import std.stdio : writeln;
writeln(some_c_function(10));
}

------------------
I then ran
gcc -Wall -fPIC -c clib.c
gcc -shared -o libclib.dll clib.o
implib libclib.lib libclib.dll

I'm getting an error on the implib command on my home computer.
Maybe running it on a different computer would work.

The LearningD book says that you should compile the libraries
with DMC on Windows, but I can't figure out how to generate a
shared library on DMC. I didn't get the implib error for what I
was working on before.

I feel like getting stuff to work with Windows is always such a
hassle, but that's the only way I'll be able to use this stuff at
work.

Jan 21
bachmeier <no spam.net> writes:
On Friday, 22 January 2016 at 02:39:33 UTC, jmh530 wrote:
I tried to create an example that more closely resembles what
is in LearningD (see
https://github.com/aldacron/LearningD/tree/master/Chapter09_Connecting%2
D%20with%20C/clib). I created two files

clib.c
----------------
#include <stdio.h>

int some_c_function(int);

int some_c_function(int a) {
printf("Hello, D! from C! %d\n", a);
return a + 20;
}

and

dclib.d
-----------------
pragma(lib, libclib.lib);

extern(C)  nogc nothrow {
int some_c_function(int);
}

void main()
{
import std.stdio : writeln;
writeln(some_c_function(10));
}

------------------
I then ran
gcc -Wall -fPIC -c clib.c
gcc -shared -o libclib.dll clib.o
implib libclib.lib libclib.dll

That should be implib /system libclib.lib libclib.dll. I'm pretty
sure the /system option is required. (Also be sure you are not
mixing 32-bit or 64-bit libraries. I don't think implib works
with 64-bit.)

I'm getting an error on the implib command on my home computer.
Maybe running it on a different computer would work.

The LearningD book says that you should compile the libraries
with DMC on Windows, but I can't figure out how to generate a
shared library on DMC. I didn't get the implib error for what I
was working on before.

You won't need to use DMC if you're using implib.

I feel like getting stuff to work with Windows is always such a
hassle, but that's the only way I'll be able to use this stuff
at work.

It definitely is more difficult.

Jan 21
Mike Parker <aldacron gmail.com> writes:
On Friday, 22 January 2016 at 02:39:33 UTC, jmh530 wrote:

The LearningD book says that you should compile the libraries
with DMC on Windows, but I can't figure out how to generate a
shared library on DMC. I didn't get the implib error for what I
was working on before.

I feel like getting stuff to work with Windows is always such a
hassle, but that's the only way I'll be able to use this stuff
at work.

Your confusion appears to be coming from a lack of understanding
of what's going on under the hood. When working with a system
language like D, it is imperative to understand what the compiler
and linker are doing. The same issues you are having can arise
when using C and C++, they are just less common as you tend to
use the same compiler toolchain for both your executable and your
libraries.

First of all, understand that DMD does not use just one linker on
Windows. The default is OPTLINK, which only works with 32-bit
object files (and by extension, library files, as they are just
archives of objects) in the OMF format. When compiling with
-m32mscoff or -m64, DMD uses the Microsoft linker, which deals
with objects in the COFF format. This matters at *link time*, not
at runtime. So it  *generally* (see below) doesn't matter which
format your DLL is in, as it is loaded at runtime no matter how
you compile.

Second, understand that when you choose to link with an import
library rather than loading the DLL manually, then it is the
format of the import library that's important. It needs to be in
the OMF format if you are compiling with vanilla DMD and in the
COFF format if not. OMF import libraries can be generated from
COFF DLLS with implib. Import libraries generated by the MinGW
toolchain are actually in the COFF format, but they are not
always compatible with the Microsoft toolchain. You are likely
going to have issues even when compiling with -m32mscoff or -m64.
Your implib difficulties may actually be arising because the DLL
was compiled with MinGW, despite it being in COFF.

Third, understand that passing -L to DMD tells it that the
succeeding flag should be passed to the linker. On Windows, -L-L
has no meaning, as neither OPTLINK nor the MS linker accept the
-L switch. -L is used with GCC to specify the library path, so in
the command line -L-L/path/to/libs, the first -L tells DMD that
the next part is for the linker and the second -L tells the
linker where to find libraries. Again, this is only for the GCC
toolchain. For DMD on Windows, how you specify the library path
depends on whether you are linking with OPTLINK or the MS linker.
As for the libraries themselves, you don't need to don't actually
need the -L flag on Windows. In fact, you can save yourself some
trouble and just pass the full path to any libraries you need
with no flags at all:

dmd myapp.d C:\path\to\libs\mylib.lib

As long as the library is in the appropriate format, this command
line will do the right thing.

I strongly recommend that you compile your DLL and generate the
import library with the Microsoft tools. Then you should be able
to use the 32-bit version with -m32mscoff and the 64-bit version
with -m64. This should /just work/.

Development on Windows is not any more difficult than on Linux.
It's annoying, sure, but not difficult. You just need to make
sure that all of the tools you are using are compatible.

Jan 21
jmh530 <john.michael.hall gmail.com> writes:
On Friday, 22 January 2016 at 04:03:27 UTC, Mike Parker wrote:
[snip]

Thanks for the detailed reply.

Jan 21
Mike Parker <aldacron gmail.com> writes:
I've take your example, modified it slightly, compiled the DLL
with Visual Studio, and got a working executable. Firs up, the C
file. Here's your original:

clib.c
----------------
#include <stdio.h>

int some_c_function(int);

int some_c_function(int a) {
printf("Hello, D! from C! %d\n", a);
return a + 20;
}

First, the function prototype is not needed. You only need those
in header files for other C modules to have access to them.
Declaring them in the same source file as the function
implementation serves no purpose.

Second, the Microsoft linker needs to know which functions you
intend to export from your DLL. In order to tell it, you either
need to add a __declspec(dllexport) to the functions you plan to
export, or provide a  module definition file on the command line
(see [1]). I opted for the former approach. With that, your C
source file looks like this:


#include <stdio.h>

__declspec(dllexport) int some_c_function(int a) {
printf("Hello, D! from C! %d\n", a);
return a + 20;
}



In the D source file, I opted to remove the pragma in favor of
passing the import library on the command line:

extern(C)  nogc nothrow {
int some_c_function(int);
}

void main()
{
import std.stdio : writeln;
writeln(some_c_function(10));
}

OK, now create the following file/folder heirarchy:

-vctest
--src
----c/clib.c
----d/dclib.d
--lib
--bin

I have Visual Studio Community 2015 installed. Whichever version
you have, you should find a folder for it in the Windows start
menu that provides shortcuts to various command prompts. I opted
for the one labeled VS2015 x64 Native Tools Command Prompt. You
might select the 32-bit (x86) version instead. Open one of them,
navigate to the vctest directory, and execute the following
command line:

cl /D_USRDLL /D_WINDLL src\c\clib.c /LD /Felib\clib.lib /link

Note the backslashes in src\c\clib.c and lib\clib.lib. You'll
likely see an error with forward slashes, unless you put the
paths in quotes (see [2] for compiler options). This should
create both clib.dll and the import library clib.lib in the lib
directory. Next, copy the dll to the bin directory:

copy lib\clib.dll bin

Now, either in the same command prompt or a separate one where
DMD is on the path (depending on your configuration), execute the
following:

dmd -m64 src/d/dclib.d lib/clib.lib -ofbin/dclib.exe

Replace -m64 with -m32mscoff if you used the 32-bit toolchain
instead of the 64-bit.

Following these steps, I produced a working executable that
output the following:

Hello, D! from C! 10
30

[1] https://msdn.microsoft.com/en-us/library/34c30xs1.aspx
[2] https://msdn.microsoft.com/en-us/library/19z1t1wy.aspx

Jan 21
jmh530 <john.michael.hall gmail.com> writes:
On Friday, 22 January 2016 at 04:43:52 UTC, Mike Parker wrote:
[snip]

Thanks again! Will review.

Jan 22
jmh530 <john.michael.hall gmail.com> writes:
On Friday, 22 January 2016 at 04:43:52 UTC, Mike Parker wrote:
[snip]

Thanks again for your help. I've worked through some simple
examples and started trying to write a binding to a C library.

I think I've got the .h file converted properly (the D file
compiles), but I was getting a linking error. The enums were
showing up, but not the functions. I tried creating a simple
project that mimics what was happening in the C library and found
no issues.

I think I narrowed it down to what is causing the linking error.
I had not compiled the C dll myself. Looking in to the issue, I
noticed it was compiled with MinGW. There were instructions for
using it with Visual Studio (to make the .def and .dll files into
a .lib) though and I assumed following those was sufficient.
However, based on what you've said, I suspect that if I
re-compile the dll using Visual Studio, then it will work with D.

I don't think I would have figured that out without your comments
above.

Feb 02
jmh530 <john.michael.hall gmail.com> writes:
On Tuesday, 2 February 2016 at 20:06:05 UTC, jmh530 wrote:
I suspect that if I re-compile the dll using Visual Studio,
then it will work with D.

Yeah, this is what finally allowed me to progress.

Unfortunately, my sample example compiles, but throws an Access
Violation error when I run it. I think I will start a new thread