DLL's and D

Chris Pons cmpons at gmail.com
Thu Mar 15 11:52:53 PDT 2012


Yes, this is a lot more clear, thanks.

On Thursday, 15 March 2012 at 05:06:16 UTC, Mike Parker wrote:
> On 3/15/2012 12:26 PM, Chris Pons wrote:
>> I haven't used DLL's much, especially one I've built on my 
>> own, so
>> guidance would be appreciated.
>>
>> I'm trying to figure out how to build a DLL which was written 
>> in D but
>> i'm not sure i'm doing this right.
>>
>> I'm using VS2010 and Visual D. Visual D has a template for 
>> Dll's in D,
>> so I used that to create a new project.
>>
>> The DLL compiles just fine, but i'm having trouble even 
>> getting import
>> to work with it. I was following the How-To on this page,
>> http://dlang.org/dll.html#Dcode , but I can't even get import 
>> to work.
>>
>> With import, is that supposed to reference the name of the 
>> DLL? So if I
>> had one named math.dll, I would write import math.dll?
>
> You are misunderstanding what the import statement does. It has 
> absolutely nothing to do with linked libraries or DLLs. It 
> works at the source level.
>
> In the example, the source module that is used to compile the 
> DLL is called mydll.d (so is the DLL, but that's irrelevant). 
> Then, in the program that uses it, you use 'import mydll;' to 
> make the declarations in that source module visible to the 
> compiler. For this to work, mydll.d has to be the import path, 
> either relative to test.d in the example, or somewhere you 
> specify with the -I switch. The actual DLL file has no part in 
> this process. It becomes involved later, in the link step.
>
> So if your math DLL has source modules named, for example, 
> math/vector.d and math/matrix.d, *those* are what you import in 
> your code.
>
> ========
> import math.vector;
> import math.matrix;
> ========
>
> As long as those modules are somewhere on the import path, 
> that's all you need. The compiler doesn't know or care about 
> the DLL itself at this point.
>
>>
>> Also, what exactly is different between the dynamic load and 
>> static link
>> in the link above?
>>
>
> I assume you already understand how to link static libraries to 
> a program -- you pass it to the linker. When using DMD, we 
> typically pass it to the compiler and it hands it off to the 
> linker for us:
>
> dmd mymodule.d someLibrary.lib
>
> That's the only way to make the symbols in a static library 
> available to the executable at runtime -- those symbols must be 
> compiled into the executable.
>
> A DLL is not compiled into the executable. It is loaded at 
> runtime. This can be done in two ways: by the operating system 
> (static load), or manually by the executable (dynamic load).
>
> In the example, you compile mydll.d and mydll.def with the 
> following command:
>
> dmd -ofmydll.dll -L/IMPLIB mydll.d dll.d mydll.def
>
> This results in mydll.dll and mydll.lib. Now, assuming 
> mydll.lib is in the same directory as test.d, you can use this 
> command to create an executable that will use static loading:
>
> dmd test.d mydll.lib
>
> The actual symbols of mydll are in mydll.dll. mydll.lib, in 
> this case, does not contain those symbols. Instead, it contains 
> the necessary information for the OS to load the DLL into 
> memory. So when the executable is launched, the OS sees that 
> information, then looks for mydll.dll automatically.
>
> For dynamic loading, you don't link with mydll.lib. Instead, 
> you have to implement some extra code in your program to load 
> the DLL and any symbols you need via the Win32 API. The last 
> example on that page does just that. It uses 
> Runtime.loadLibrary (which, under the hood, uses the Win32 
> function LoadLibrary) to load the DLL. It then loads the 
> getMyClass function using the Win32 function GetProcAddress. 
> Note that it uses the fully mangled name of the function to do 
> so.
>
> So, to dynamically load the mydll example, you would add code 
> to test.d to load mydll.dll and to load the pointer for the 
> print function. To compile, you would do this:
>
> dmd test.d
>
> You no longer need to link with mydll.lib, since you are 
> loading the library manually (dynamically).
>
>> Would I need to load the DLL for every module that imports it?
>
> No. Once the executable is compiled, the concept of modules 
> essentially disappears. Everything is loaded into memory. The 
> DLL is loaded into the executable's address space exactly one 
> time. This makes the symbols available to everything in the 
> same process. Even if you were to manually load the DLL 
> multiple times with Runtime.loadLibrary, the OS would only 
> actually load it once.
>
> I believe you've used Derelict, yes? When you call something 
> like DerelictSDL2.load(), Derelict dynamically loads the SDL2 
> DLL into memory. You only need to call it at one point in your 
> program. After that, it's available to everything in your 
> program. But you still need to import the derelict.sdl2.sdl 
> module into every module uses it so that the compiler knows 
> which declarations are available for you to use. Source modules 
> are used at compile time and must be imported into every module 
> that uses them. DLLs are used at runtime and are only loaded 
> into memory once. I suggest you read up on the difference 
> between compilation, linkage, and execution of a program for 
> the reasons behind all of this to become more clear.
>
>>
>> Do I need to use the export keyword for every 
>> class/function/etc that is
>> meant to be used outside of the DLL?
>>
>
> Unfortunately, it's not possible to export D classes from DLLs. 
> So you don't need the export keyword on classes. But you do 
> need it on all of the functions and variables that should be 
> visible outside of the DLL. This is exactly what is 
> demonstrated in the section, 'D Code calling D code in DLLs' of 
> that page you linked above.
>
>
>> Also, the DLL i'm trying to make, has several modules, can I 
>> import a
>> specific module from the dll? Like, import math.calculus if 
>> calculus was
>> a module in the math DLL?
>>
>>
> Again, you don't import modules "from a DLL". Modules are 
> source files used by the compiler at compile time. If you have 
> class Foo in bar.d, you have to import bar into any module 
> where you want to use the Foo class. Otherwise, the compiler 
> doesn't even know that the Foo class exists. So, by importing 
> math.calculus any given module, you are telling the compiler 
> which source declarations exist and are available for that 
> module to use. The compiler uses all of that information to 
> compile all of the symbols into object files.
>
> At runtime, we are no longer concerned with source 
> declarations, but with binary symbols that are loaded in 
> memory. Some of those symbols will be part of the executable 
> file (either compiled in one step or statically linked). Some 
> will be part of a DLL that is loaded into memory separately 
> from the executable. But none of them have anything to do with 
> the import statement.
>
> I hope that helps.




More information about the Digitalmars-d-learn mailing list