July 02, 2022

On Saturday, 2 July 2022 at 00:23:20 UTC, Ruby The Roobster wrote:

>

The solution is to remove the extern declaration. That does it for me, and it prints the expected output. No need for a .def file, unless you are using optlink as your linker (which, as a matter of principle, you should use lld or ld instead.)

Thank you for the reply. Let me try that.

July 01, 2022
On 7/1/22 12:11, Vinod KC wrote:

The following function is dimedll.testFunc:

> ```d
> module dimedll;
// ...
> export void testFunc() {
>      writeln("This is from dll");
> }
> ```

We suspect the name of the file that defines main() is dime.d.

> extern void testFunc();

That symbol belongs to this module, which is implied to be 'module dime'.

>      testFunc();

That's a call to dime.testFunc, which does not exist.

With the provided information alone, the following is what I would do:

1) This dll must have a .di file, which should contain the following:

// dimedll.di
void testFunc();

(.di files can be generated by dmd with its -H command line switch.)

2) Provide dimedll.di as your library's interface file (a la "header file").

3) The users of this dll should import that .di file (declaring the functions themselves won't work):

import dimedll;

void main() {
  // ...
}

Ali

July 02, 2022

On Saturday, 2 July 2022 at 01:05:25 UTC, Ali Çehreli wrote:

>
  1. The users of this dll should import that .di file (declaring the functions themselves won't work):
    Ali

Hi, Thanks for the reply. I have tried your suggestion. First, I compiled my dll's source code with -H switch as you said. Then I got the header file with this content.

// D import file generated from dimedll.d
module dimedll;
import core.sys.windows.windows;
import core.sys.windows.dll;
import std.stdio;
mixin SimpleDllMain!();
export void testFunc();

So far so good. Then I change my dime.d source file like this.

```d
import dimedll;
void main() { 	
    log("Lets build our own ime");
    testFunc();	
}
```
Unfortunately, I got this error message.

dime.obj : error LNK2019: unresolved external symbol __imp___D7dimedll8testFuncFZv referenced in function __Dmain
dime.obj : error LNK2001: unresolved external symbol __D7dimedll12__ModuleInfoZ
dime.exe : fatal error LNK1120: 2 unresolved externals
Error: linker exited with status 1120

Then I have tested with dimedll.testFunc() instead of testFunc() at the calling site.
Then also I got an error message like this.

dime.obj : error LNK2019: unresolved external symbol __imp___D7dimedll8testFuncFZv referenced in function __Dmain
dime.obj : error LNK2001: unresolved external symbol __D7dimedll12__ModuleInfoZ
dime.exe : fatal error LNK1120: 2 unresolved externals
Error: linker exited with status 1120

I want to test this with ddemangle.exe, but there is no proper documentation for that tool. So I don't know how to use that tool. So Actually I am stuck.
July 02, 2022

With LDC, this is sufficient for this trivial example:

module dimedll;

export void testFunc() { // export only needed when compiling with `-fvisibility=hidden`
    import std.stdio;
    writeln("This is from dll");
}

ldc2 -shared dimedll.d generates import lib + DLL.

import dimedll : testFunc;

pragma(lib, "dimedll");

void main() {
    import std.stdio;
    writeln("Lets build our own ime");
    testFunc();
}

ldc2 -link-defaultlib-shared dime.d generates the .exe and makes it share the druntime/Phobos DLLs with dimedll.dll. (More complex cases might need -dllimport=all).

C:\temp\dllTest>dime
Lets build our own ime
This is from dll

C:\temp\dllTest>dir
…
07/02/2022  03:54 PM               155 dime.d
07/02/2022  03:57 PM            18,432 dime.exe
07/02/2022  03:57 PM            19,679 dime.obj
07/02/2022  03:56 PM               162 dimedll.d
07/02/2022  03:57 PM            20,480 dimedll.dll
07/02/2022  03:57 PM             7,534 dimedll.exp
07/02/2022  03:56 PM            13,036 dimedll.lib
07/02/2022  03:57 PM            21,233 dimedll.obj

On Posix, the only difference is that one would have to link libdimedll.{so,dylib} explicitly via -L-ldimedll instead of the pragma(lib).

July 02, 2022

Below is working on Windows

--file dimedll.d:

module dimedll;
import core.sys.windows.windows;
import core.sys.windows.dll;
import std.stdio;

mixin SimpleDllMain;

export void testFunc()
{
    writeln("This is from dll");
}

--file dime.d:

import core.sys.windows.windows;
import std.stdio;
import dimedll;
pragma(lib, "dimedll.lib");

void main() { 	
	writeln("Lets call testFunc()");
	testFunc();		
}

--file dimedll.di:

module dimedll;
extern void testFunc();

--file dimedll.def

LIBRARY "dimedll.dll"
EXETYPE NT
SUBSYSTEM WINDOWS
CODE SHARED EXECUTE
DATA WRITE

-- command lines in sequence:
-- there should be files as first dmd: dimedll.exp, dimedll.lib, dimedll.obj

dmd -of=dimedll.dll dimedll.d dimedll.def
dmd dime.d dimedll.di

July 02, 2022

On Saturday, 2 July 2022 at 14:32:11 UTC, apz28 wrote:

>

dmd -of=dimedll.dll dimedll.d dimedll.def
dmd dime.d dimedll.di

Thanks for the reply. Well, I am sorry to say that your suggestions resulted in failure.
First of all, when I used this command -- dmd -of=dimedll.dll dimedll.d dimedll.def I got this error message-
Error: unrecognized file extension dll.
So I avoided the -of=dimedll.dll part.
Then I compiled it with this command - dmd -H dimedll.d dimedll.def
And I got some warnings. Here are they.

dimedll.def(2) : warning LNK4017: EXETYPE statement not supported for the target platform; ignored
dimedll.def(3) : warning LNK4017: SUBSYSTEM statement not supported for the target platform; ignored
dimedll.def(4) : warning LNK4017: CODE statement not supported for the target platform; ignored
dimedll.def(4) : warning LNK4017: DATA statement not supported for the target platform; ignored
   Creating library dimedll.lib and object dimedll.exp

I know all of them are from my def file. Anyways, I stepped forward and tried to run the main file with this dll & lib.
So I ran this command. - dmd dime.d dimedll.di. But I got this error message.

dime.obj : error LNK2001: unresolved external symbol __D7dimedll12__ModuleInfoZ
dime.exe : fatal error LNK1120: 1 unresolved externals
Error: linker exited with status 1120
July 02, 2022

On Saturday, 2 July 2022 at 20:43:41 UTC, Vinod KC wrote:

>

On Saturday, 2 July 2022 at 14:32:11 UTC, apz28 wrote:

>

dmd -of=dimedll.dll dimedll.d dimedll.def
dmd dime.d dimedll.di

Thanks for the reply. Well, I am sorry to say that your suggestions resulted in failure.
First of all, when I used this command -- dmd -of=dimedll.dll dimedll.d dimedll.def I got this error message-
Error: unrecognized file extension dll.

Actually, can you create a github repo, I'm sure people will send you a working PR.

July 03, 2022

On Saturday, 2 July 2022 at 21:36:50 UTC, mw wrote:

>

Actually, can you create a github repo, I'm sure people will send you a working PR.

Yes I can. I will inform here once I did it.

July 03, 2022

On Saturday, 2 July 2022 at 14:06:03 UTC, kinke wrote:

>

With LDC, this is sufficient for this trivial example:

module dimedll;

export void testFunc() { // export only needed when compiling with `-fvisibility=hidden`
    import std.stdio;
    writeln("This is from dll");
}

ldc2 -shared dimedll.d generates import lib + DLL.

import dimedll : testFunc;

pragma(lib, "dimedll");

void main() {
    import std.stdio;
    writeln("Lets build our own ime");
    testFunc();
}

ldc2 -link-defaultlib-shared dime.d generates the .exe and makes it share the druntime/Phobos DLLs with dimedll.dll. (More complex cases might need -dllimport=all).

C:\temp\dllTest>dime
Lets build our own ime
This is from dll

C:\temp\dllTest>dir
…
07/02/2022  03:54 PM               155 dime.d
07/02/2022  03:57 PM            18,432 dime.exe
07/02/2022  03:57 PM            19,679 dime.obj
07/02/2022  03:56 PM               162 dimedll.d
07/02/2022  03:57 PM            20,480 dimedll.dll
07/02/2022  03:57 PM             7,534 dimedll.exp
07/02/2022  03:56 PM            13,036 dimedll.lib
07/02/2022  03:57 PM            21,233 dimedll.obj

On Posix, the only difference is that one would have to link libdimedll.{so,dylib} explicitly via -L-ldimedll instead of the pragma(lib).

>

This is from dll

Are you sure? You import testFunc as normal import, the compiler ignores pragma(lib) - that's only for the linker which will ignore it too since the symbol is already in your executable. If you can run your exectuable without dimedll.dll present, then the function is not statically linked in.

A static linked function should generate a very small lib-file and yours look too big to me.

I don't know about LDC but with DMD I struggle with static linked DLLs because the library generated does not link to the DLL. To get right results, I need to pass the linker flag --L=/IMPLIB (or -L=/DLL for 64bit) to generate a lib-file that is really linked to the DLL later.

July 03, 2022

On Saturday, 2 July 2022 at 20:43:41 UTC, Vinod KC wrote:

>

But I got this error message.
dime.obj : error LNK2001: unresolved external symbol __D7dimedll12__ModuleInfoZ
dime.exe : fatal error LNK1120: 1 unresolved externals
Error: linker exited with status 1120

I tried the -H switch. You can't rely on that. I comment the lines that shouldn't be there - then it should work:

dimedll.di

// D import file generated from 'dimedll.d'
module dimedll;
// import core.sys.windows.dll;
// import std.stdio;
// mixin SimpleDllMain!();
export void testFunc();

dimedll.d:

module dimedll;

import core.sys.windows.dll;
import std.stdio;

mixin SimpleDllMain;

export void testFunc() {
    writeln("This is from dll");
}

app.d:

module app;
import dimedll;

import std.stdio;
import std.stdio : log = writeln;

pragma(lib, "dimedll.lib");

void main() { 	
   log("Lets build our own ime");
   testFunc();		
}

You should be able to change contents in the DLL and run the executable wihtout re-compiling (the library file should be round ~2kB).

PS: ddemangle just waits for your input. You copy in the mangled symbol like __D7dimedll12__ModuleInfoZ and press enter ;-)