www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Creating DLL

reply Sergeant <aldrichgreenwald gmail.com> writes:
Hi,
I wonder if anyone knowledgeable can point me in the right 
direction here.
I created DLL in Visual D, but when I try to use it by my 
application (AHK script), DLL itself is loaded ok, but error is 
set to "specified function could not be found inside the DLL". 
(Same DLL that I made in C++ works, but this doesn't somehow)

Sample code looks like this:

	module my_dll;

	import core.sys.windows.windows;
	import core.sys.windows.dll;

     export int my(int a, int b)
     {
       // ... my code ...
       // return output;
     }

	mixin SimpleDllMain;

I set "-shared" switch in VS. Is there anything I'm missing here?
Thanks!
Jun 16 2022
parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Thursday, 16 June 2022 at 13:57:48 UTC, Sergeant wrote:
     export int my(int a, int b)
the name here is going to be mangled, so like "_D5mydll2myiiZi" or something like that. You might want to add `extern(C)` to it so it keeps the simple name "my", that might help.
Jun 16 2022
parent reply Sergeant <aldrichgreenwald gmail.com> writes:
Adam thank you, it works now!

May I ask one more question: why a code like this would work in 
D-application but not in D-DLL? (also I notice some other D 
functions don't work in DLL):

	import std.string;

	export extern(C) string my(string input)
	{
	string output = "";
	auto lines = input.lineSplitter();
	foreach (line; lines){
		output ~= line;
	}
	return output
	}
Jun 16 2022
next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Thursday, 16 June 2022 at 16:07:41 UTC, Sergeant wrote:
 May I ask one more question: why a code like this would work in 
 D-application but not in D-DLL? (also I notice some other D 
 functions don't work in DLL):
Probably because the runtime not initialized properly. Export an Initialize() and Terminate() functions and call them from your application loading the dll. Inside those functions: export extern(C) void Initialize() { import core.runtime; Runtime.initialize(); } export extern(C) void Terminate() { import core.runtime; Runtime.terminate(); } If you call those the other functions should start working. (this is a fairly common thing libraries need to do, but it might be tricky if you are loading the dll into an uncooperative application, there's other hacks for that, but having your functions like this and the app calling them are the right way to do it)
Jun 16 2022
parent Sergeant <aldrichgreenwald gmail.com> writes:
Adam, thank you again!

Adding Initialize()/Terminate() to code and calling from my 
application as you suggested didn't help, unfortunately. Maybe 
the problem is in the scripting language I'm using (AHK) which is 
not designed to handle situations like these.

In any case, appreciate your help!
Jun 16 2022
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 6/16/22 09:07, Sergeant wrote:

 May I ask one more question: why a code like this would work in
 D-application but not in D-DLL?
D programs generated by D compilers automatically initialize the D runtime. You can do the same with rt_init: pragma (crt_constructor) extern(C) int initialize() { // Can have any name return rt_init(); } And to deinitialize; pragma (crt_destructor) extern(C) int terminate() { // Can have any name return rt_term(); } Although, I haven't tested it with a DLL but with .so libraries on Linux... :/ This answer may be relevant: https://forum.dlang.org/post/t8diks$2l79$1 digitalmars.com Ali
Jun 16 2022
next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Thursday, 16 June 2022 at 16:19:22 UTC, Ali Çehreli wrote:
 pragma (crt_constructor)
You have to be pretty careful about this since it might not run in the order you expect. If there's two things in the program with a equal-priority crt constructor, they are run in arbitrary order. In a shared lib, there's also the possibility that loader locks are in place, and if it runs rt_init specifically, that can run D module constructors... which might load other libraries. Similar concerns apply to doing rt_init in DllMain. This is why an explicit initialization call is the preferred method - there, the time it is called is well-defined by the user after initial loading is complete.
Jun 16 2022
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 6/16/22 09:32, Adam D Ruppe wrote:

 This is why an explicit initialization call is the preferred method -
 there, the time it is called is well-defined by the user after initial
 loading is complete.
Agreed but that excludes using the D runtime in 'static this' (and shared) blocks, right? If my explicit call to Initialize is in a 'shared static this', then I can have only one such block, right? Ali
Jun 16 2022
parent Adam D Ruppe <destructionator gmail.com> writes:
On Thursday, 16 June 2022 at 16:37:34 UTC, Ali Çehreli wrote:
 Agreed but that excludes using the D runtime in 'static this' 
 (and shared) blocks, right?
It is runtime.initialize that calls those `static this` blocks.
 If my explicit call to Initialize is in a 'shared static this'
This is backward - the explicit call to Initalize is in the exe. It'd look like: // this code is in the exe! pretend it is C++ or whatever HANDLE lib = LoadLibrary("my_d_lib.dll"); if(lib !is null) { auto fn = cast(typeof(init_func)) GetProcAddress("Initialize"); if(fn !is null) { fn(); // this now calls runtime.initialize which calls the static this blocks etc // you're now good to call any D functions } }
Jun 16 2022
prev sibling parent Sergeant <aldrichgreenwald gmail.com> writes:
On Thursday, 16 June 2022 at 16:19:22 UTC, Ali Çehreli wrote:
 On 6/16/22 09:07, Sergeant wrote:

 This answer may be relevant:

   https://forum.dlang.org/post/t8diks$2l79$1 digitalmars.com
Ali, thank you, I'll take a look.
Jun 16 2022