Jump to page: 1 2
Thread overview
Dynamically calling external libraries.
Feb 26, 2014
Setra
Feb 26, 2014
Adam D. Ruppe
Feb 26, 2014
Mike James
Feb 26, 2014
John Colvin
Feb 27, 2014
Setra
Feb 27, 2014
Marc Schütz
Feb 27, 2014
Setra
Feb 28, 2014
Setra
Feb 28, 2014
Marc Schütz
Feb 28, 2014
Setra
Feb 28, 2014
Tolga Cakiroglu
Feb 28, 2014
Marc Schütz
Feb 28, 2014
Marc Schütz
Feb 28, 2014
Setra
February 26, 2014
Hello all! I am in the process of creating a programming
language, and I have completed parsing for most of the actual
language (it is interpreted). I do not however have a way to
print to the screen yet. This is because I want to use external
libraries. My question is how in D can I call a external library
that is specified at runtime not compile time? I want the
scripting language to be able to specifiy a library to load /
call, and then do so while running. Any thoughts of how to do
this?

Thanks! -Setra
February 26, 2014
You'd do it the same way you do in C. On Windows, call LoadLibrary, FreeLibrary, and GetProcAddress or the COM functions. On Linux, the family of functions is dlopen, dlsym, and dlclose.

Knowing the types to pass the functions is gonna be tricky and this needs to be right to avoid crashes. On Windows with scripting language, this is often done through COM automation: the IDispatch interface. With regular C functions, you really just have to know the prototypes ahead of time... it won't be fully dynamic, you load the library at run time but know how to use it at compile time.
February 26, 2014
On Wednesday, 26 February 2014 at 14:41:02 UTC, Adam D. Ruppe wrote:
> You'd do it the same way you do in C. On Windows, call LoadLibrary, FreeLibrary, and GetProcAddress or the COM functions. On Linux, the family of functions is dlopen, dlsym, and dlclose.
>
> Knowing the types to pass the functions is gonna be tricky and this needs to be right to avoid crashes. On Windows with scripting language, this is often done through COM automation: the IDispatch interface. With regular C functions, you really just have to know the prototypes ahead of time... it won't be fully dynamic, you load the library at run time but know how to use it at compile time.

That's the way I do it but I was wondering. Is it better to load all the functions from the DLL at the start of the program or load them when required and keep having to check if they're loaded before each use?

-<Mike>-
February 26, 2014
On Wednesday, 26 February 2014 at 17:58:46 UTC, Mike James wrote:
> On Wednesday, 26 February 2014 at 14:41:02 UTC, Adam D. Ruppe wrote:
>> You'd do it the same way you do in C. On Windows, call LoadLibrary, FreeLibrary, and GetProcAddress or the COM functions. On Linux, the family of functions is dlopen, dlsym, and dlclose.
>>
>> Knowing the types to pass the functions is gonna be tricky and this needs to be right to avoid crashes. On Windows with scripting language, this is often done through COM automation: the IDispatch interface. With regular C functions, you really just have to know the prototypes ahead of time... it won't be fully dynamic, you load the library at run time but know how to use it at compile time.
>
> That's the way I do it but I was wondering. Is it better to load all the functions from the DLL at the start of the program or load them when required and keep having to check if they're loaded before each use?
>
> -<Mike>-

Normally one loads it at the start. In the case of an optional feature depending on a shared library, you can always set a global flag (probably shared/__gshared) to say whether the load was successful and use that later on to check.
February 27, 2014
I have found the Dlang wiki article on how to do it. http://dlang.org/dll-linux.html

I am using the following code.

[code]
import core.stdc.stdio;
import core.stdc.stdlib;
import core.sys.posix.dlfcn;

extern (C) int dll();

int main() {
  printf("+main()\n");

  void *lh = dlopen("libdll.so", RTLD_LAZY);
  if (!lh) {
    fprintf(stderr, "dlopen error: %s\n", dlerror());
    exit(1);
  }
  printf("libdll.so is loaded\n");

  int function(int x) fn = cast(int function(int x))dlsym(lh, "dll");

  printf("dll() function is found\n");

  fn(72);

  printf("unloading libdll.so\n");
  dlclose(lh);

  printf("-main()\n");
  return 0;
}
[\code]

[code]
import core.stdc.stdio;
import std.stdio;

extern (C) int dll(int x) {
  printf("dll()\n");
	writeln(x);
  return 0;
}
[\code]

I am compiling it the way to guide recomends it. It compiles however for some reason when it runs the value returned by the dll is incorrect? Does anyone know why? It always returns the same value even when I change the parameter.
Thanks!
February 27, 2014
On Thursday, 27 February 2014 at 14:38:11 UTC, Setra wrote:
> I am compiling it the way to guide recomends it. It compiles however for some reason when it runs the value returned by the dll is incorrect? Does anyone know why? It always returns the same value even when I change the parameter.

What do you mean by "returns"? You're not actually printing the return value of fn(). Are you referring to the value printed in dll()?

For me this works (openSUSE 13.1, DMD git master):
# dmd main1.d -L-ldl
# dmd -c dll.d -fPIC
# dmd -oflibdll.so dll.o -shared -defaultlib=
# LD_LIBRARY_PATH=. ./main1
+main()
libdll.so is loaded
dll() function is found
dll()
72
unloading libdll.so
-main()

(I had to remove the "import std.stdio" and change the writeln() to printf("%d", x) to get it to link because of an undefined symbol.)
February 27, 2014
By returns I ment what it wrote to the screen. I realise now that that was a bad word to use... Every time I run it I get the value 134515512. Here is my compile script (Note I edited my code to use the same method of printing that you did and got the same result):

dmd -c dll.d -fPIC
dmd -oflibdll.so dll.o -shared -defaultlib=libphobos2.so -L-rpath=/path/to/where/shared/library/is

dmd -c main.d
dmd main.o -L-ldl -defaultlib=libphobos2.so -L-rpath=.:/path/to/where/shared/library/is -map

./main

Thanks!
February 28, 2014
Marc would you be willing to post your compile script? Or did you just use what the wiki said to?
February 28, 2014
On Friday, 28 February 2014 at 16:44:02 UTC, Setra wrote:
> Marc would you be willing to post your compile script? Or did you just use what the wiki said to?

I used exactly what I quoted in my post:

dmd main1.d -L-ldl
dmd -c dll.d -fPIC
dmd -oflibdll.so dll.o -shared -defaultlib=
LD_LIBRARY_PATH=. ./main1

But what you just wrote works correctly, too.

Are you sure you're actually using the correct object files? I.e. try deleting all output files first. Sometimes it's really trivialities like this :-)

Or it's an architectural problem? I'm on x86_64, maybe you're compiling 32bit code (although of course that should work, but you can never know)?

Which version of DMD are you using?

Otherwise you could try disassembling things or single-step through the call with a debugger.

But maybe someone else knows something better?
February 28, 2014
I am using  dmd_2.065.0-0_i386.deb on a 32 bit machine.
« First   ‹ Prev
1 2