Jump to page: 1 2 3
Thread overview
Shared libraries/DLLs
Feb 01, 2008
Neal Alexander
Feb 04, 2008
bearophile
Feb 04, 2008
Neal Alexander
Feb 01, 2008
Bjoern
February 01, 2008
This might be a silly or simple question.  I haven't really used shared libraries very much, but have need to now.

On Linux with gdc, everything (seems to be) fine.  I can make everything work there fine.  My problem is with Windows and dmd.

Consider the following simple "library":

---
module library;

import loader;

// (the DllMain stuff from D's doc pages.)

extern (C)
export int foo()
{
	return 42 * loader.bar();
}
---

And also consider this "application":

---
module loader;

import std.c.windows.windows;
import std.string, std.stdio;

extern (C)
alias int function() example_f;

void main()
{
	HMODULE m = cast(HMODULE) LoadLibraryA(toStringz("library.dll"));

	example_f f = cast(example_f) GetProcAddress(m, toStringz("foo"));

	if (f)
		writefln("%d", f());

	FreeLibrary(m);
}

extern (C)
export int bar()
{
	return 2;
}
---

This appears to work on Linux.  I expected it might work (or there might be some way to coax it to work) on Windows.  It seems logical, even not having used the LoadLibrary/etc. stuff before.  The library needs to access the caller's functions.

It does appear I can make it at least *compile* (but not run) by adding an IMPORTS directive to the .def file of the library, but this clearly is intended for static linking.  I'm wanting to load the DLL as a plugin, dynamically.  Its name and location might change.

Am I making some hopefully obvious and stupid mistake?  Please tell me I don't actually have to send pointers to all the api functions to the DLL when calling it.

Thanks,
-[Unknown]
February 01, 2008
"Unknown W. Brackets" <unknown@simplemachines.org> wrote in message news:fnu7l0$2p5l$1@digitalmars.com...

> This appears to work on Linux.  I expected it might work (or there might be some way to coax it to work) on Windows.  It seems logical, even not having used the LoadLibrary/etc. stuff before.  The library needs to access the caller's functions.
>
> It does appear I can make it at least *compile* (but not run) by adding an IMPORTS directive to the .def file of the library, but this clearly is intended for static linking.  I'm wanting to load the DLL as a plugin, dynamically.  Its name and location might change.
>
> Am I making some hopefully obvious and stupid mistake?  Please tell me I don't actually have to send pointers to all the api functions to the DLL when calling it.

So, uh, what _exactly_ is the problem?  I don't think you ever said..


February 01, 2008
Sorry, I want to be able to compile and run that.  It refuses to do so.

It wants to link against loader.obj, except that defeats the purpose of it being dynamic.  I can add IMPORTS to the def, but then it has to be static.

I want to dynamically link, and also call functions from the code that is dynamically linking.

Sorry I was unclear.

-[Unknown]


Jarrett Billingsley wrote:
> "Unknown W. Brackets" <unknown@simplemachines.org> wrote in message news:fnu7l0$2p5l$1@digitalmars.com...
> 
>> This appears to work on Linux.  I expected it might work (or there might be some way to coax it to work) on Windows.  It seems logical, even not having used the LoadLibrary/etc. stuff before.  The library needs to access the caller's functions.
>>
>> It does appear I can make it at least *compile* (but not run) by adding an IMPORTS directive to the .def file of the library, but this clearly is intended for static linking.  I'm wanting to load the DLL as a plugin, dynamically.  Its name and location might change.
>>
>> Am I making some hopefully obvious and stupid mistake?  Please tell me I don't actually have to send pointers to all the api functions to the DLL when calling it.
> 
> So, uh, what _exactly_ is the problem?  I don't think you ever said.. 
> 
> 
February 01, 2008
Unknown W. Brackets wrote:
> Sorry, I want to be able to compile and run that.  It refuses to do so.
> 
> It wants to link against loader.obj, except that defeats the purpose of it being dynamic.  I can add IMPORTS to the def, but then it has to be static.
> 
> I want to dynamically link, and also call functions from the code that is dynamically linking.
> 
> Sorry I was unclear.
> 
> -[Unknown]
> 
> 
> Jarrett Billingsley wrote:
>> "Unknown W. Brackets" <unknown@simplemachines.org> wrote in message news:fnu7l0$2p5l$1@digitalmars.com...
>>
>>> This appears to work on Linux.  I expected it might work (or there might be some way to coax it to work) on Windows.  It seems logical, even not having used the LoadLibrary/etc. stuff before.  The library needs to access the caller's functions.
>>>
>>> It does appear I can make it at least *compile* (but not run) by adding an IMPORTS directive to the .def file of the library, but this clearly is intended for static linking.  I'm wanting to load the DLL as a plugin, dynamically.  Its name and location might change.
>>>
>>> Am I making some hopefully obvious and stupid mistake?  Please tell me I don't actually have to send pointers to all the api functions to the DLL when calling it.
>>
>> So, uh, what _exactly_ is the problem?  I don't think you ever said..
>>

If the settings used in your .def file aren't particular the DLL doesnt work as expected. IIRC the def files in the digital mars DLL tutorial diddnt work for me when i first looked at it.

maybe try this instead:
-----------------------------------
LIBRARY "x.dll"
DESCRIPTION 'x.dll'

EXETYPE NT
CODE PRELOAD
DATA PRELOAD
February 01, 2008
Thanks.  Actually, I have no trouble whatsoever making dlls.  I have a problem referencing functions in the program that loaded the DLL.

It turns out (from something I'm read) what I want is simply not possibly with DLLs.  I will have to send a pointer table/struct over on to the plugin for this to work the way I want.

Ain't Linux better?  Oi.

-[Unknown]


Neal Alexander wrote:
> If the settings used in your .def file aren't particular the DLL doesnt work as expected. IIRC the def files in the digital mars DLL tutorial diddnt work for me when i first looked at it.
> 
> maybe try this instead:
> -----------------------------------
> LIBRARY "x.dll"
> DESCRIPTION 'x.dll'
> 
> EXETYPE NT
> CODE PRELOAD
> DATA PRELOAD
February 01, 2008
Hm,
1-
__declspec(dllimport) int __stdcall foo();
becomes :
export extern(Windows) int foo();

so, I would give extern(Windows) instead of extern(C) a try to avoid name mangeling problems.

2-
Just guessing :
You have module library "DLLMain()" and loader "main()" try to place main() in a seperate file.

3-
UNKNOWN WROTE :
"I want to dynamically link, and also call functions from the code that is dynamically linking."

I can imagine that using callbacks is an interesting option to establish plugings, like :

//THE DLL
// define the callback function.
alias extern(Windows) void function(char* token, size_t siz = 0, bool error =false) DisplayCallBack;


export extern(Windows)
void ExecuteProcess(DisplayCallBack cb, char* _dir, char* _command, char* _args)
{
  //do someting and call CallBack function defined in Application
  cb(tok, tok_size)
}

HTH Bjoern
February 01, 2008
"Unknown W. Brackets" <unknown@simplemachines.org> wrote in message news:fnuiqt$ags$1@digitalmars.com...
> Thanks.  Actually, I have no trouble whatsoever making dlls.  I have a problem referencing functions in the program that loaded the DLL.

You shouldn't need a .def file at all for this program.  In fact, you should be able to compile the app the same way you compile any other app.  That it loads a dynamic library at runtime means nothing to the compiler/linker.

> Ain't Linux better?  Oi.

DLLs are a pretty awful approximation of SOs, yes.


February 01, 2008
Well, the def being for the library, not for the program loading the library.  Otherwise I don't get exports named properly, etc.

-[Unknown]


Jarrett Billingsley wrote:
> "Unknown W. Brackets" <unknown@simplemachines.org> wrote in message news:fnuiqt$ags$1@digitalmars.com...
>> Thanks.  Actually, I have no trouble whatsoever making dlls.  I have a problem referencing functions in the program that loaded the DLL.
> 
> You shouldn't need a .def file at all for this program.  In fact, you should be able to compile the app the same way you compile any other app.  That it loads a dynamic library at runtime means nothing to the compiler/linker.
> 
>> Ain't Linux better?  Oi.
> 
> DLLs are a pretty awful approximation of SOs, yes. 
> 
> 
February 01, 2008
"Unknown W. Brackets" <unknown@simplemachines.org> wrote in message news:fnvd2q$229m$1@digitalmars.com...
> Well, the def being for the library, not for the program loading the library.  Otherwise I don't get exports named properly, etc.

In that case, I'd be more interested to see how you're compiling all this code.  The code itself looks very simplistic, and I don't see any apparent failure points.


February 02, 2008
Okay.

Example "plugin" example.d:

---
module example;

extern (C)
export int foo();

version (Windows)
	import utils.windows;

extern (C)
export int example()
{
	return 42 + foo();
}
---

Compiled with:

$(DMD) $(DFLAGS_DEBUG) -op -of$(OUTPUT) $(LIBS) $(wildcard utils/*.d) example.d example.def

Or:

$(GDMD) $(DFLAGS_DEBUG) -op -of$(OUTPUT) $(LIBS) $(wildcard utils/*.d) example.d -fPIC -q,-rdynamic,-shared


Plugin linker definition file:

---
LIBRARY         example.dll
DESCRIPTION     'Example'

EXETYPE         NT
SUBSYSTEM       WINDOWS 4.0
CODE            PRELOAD SHARED DISCARDABLE
DATA            PRELOAD SINGLE

EXPORTS
				example
---


Example host program for Windows, load_test.d:

---
module load_test;

import std.c.windows.windows;
import std.string, std.stdio;

extern (C)
	alias int function() example_f;

int main()
{
	HMODULE m = cast(HMODULE) LoadLibraryA(toStringz("example.dll"));

	example_f f = cast(example_f) GetProcAddress(m, toStringz("example"));

	if (f)
		writefln("%d", f());

	FreeLibrary(m);

	return 0;
}

extern (C)
export int foo()
{
	return 43;
}
---


Quick DllMain file from samples, utils/windows.d:

---
module utils.windows;

version (Windows):

import std.c.windows.windows;

extern (C)
{
	void gc_init();
	void gc_term();
	void _minit();
	void _moduleCtor();
	void _moduleUnitTests();

	HINSTANCE g_hInst;
}

extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
    switch (ulReason)
    {
	case DLL_PROCESS_ATTACH:
	    gc_init();			// initialize GC
	    _minit();			// initialize module list
	    _moduleCtor();		// run module constructors
	    _moduleUnitTests();		// run module unit tests
	    break;

	case DLL_PROCESS_DETACH:
	    gc_term();			// shut down GC
	    break;

	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	default:
	    // Multiple threads not supported yet
	    return false;
    }

    g_hInst = hInstance;
    return true;
}
---

I don't have the Linux loader in front of me but it's almost exactly the same and works just fine (LoadLibraryA => dlopen, GetProcAddress => dlsym, FreeLibrary => dlclose, with some dlerror logic in there.)  But as stated, it appears that there's really no "reverse linking" of DLLs.

-[Unknown]


Jarrett Billingsley wrote:
> "Unknown W. Brackets" <unknown@simplemachines.org> wrote in message news:fnvd2q$229m$1@digitalmars.com...
>> Well, the def being for the library, not for the program loading the library.  Otherwise I don't get exports named properly, etc.
> 
> In that case, I'd be more interested to see how you're compiling all this code.  The code itself looks very simplistic, and I don't see any apparent failure points. 
> 
> 
« First   ‹ Prev
1 2 3