www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.internals - How do I find and call a function in a module I only know during

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Say I have a module "a" that wants to call a function "void fun()" in 
another module "b". The name "b" is not known until runtime, i.e. it's 
read from the console. (Really the name is obtained by iterating foreach 
(m; ModuleInfo)).

How do I get fun()'s address (or the null pointer if it doesn't exist)?


Thanks,

Andrei
Dec 26 2016
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-12-26 19:45, Andrei Alexandrescu wrote:
 Say I have a module "a" that wants to call a function "void fun()" in
 another module "b". The name "b" is not known until runtime, i.e. it's
 read from the console. (Really the name is obtained by iterating foreach
 (m; ModuleInfo)).

 How do I get fun()'s address (or the null pointer if it doesn't exist)?
Perhaps use "dlopen" on the executable and then use "dlsym" and pass in the mangled name. -- /Jacob Carlborg
Dec 26 2016
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/26/2016 03:01 PM, Jacob Carlborg wrote:
 On 2016-12-26 19:45, Andrei Alexandrescu wrote:
 Say I have a module "a" that wants to call a function "void fun()" in
 another module "b". The name "b" is not known until runtime, i.e. it's
 read from the console. (Really the name is obtained by iterating foreach
 (m; ModuleInfo)).

 How do I get fun()'s address (or the null pointer if it doesn't exist)?
Perhaps use "dlopen" on the executable and then use "dlsym" and pass in the mangled name.
Yah, I'm trying this: void main() { void *hndl = dlopen(null, 1); hndl !is null || assert(0); auto n = "runAllTests".ptr;//m.name ~ "" '\0'; auto p = cast(void function()) dlsym(hndl, n); if (!p) assert(0); p(); } extern(C) void* dlopen(const(char)*, int); extern(C) void* dlsym(void*, const(char)*); export extern(C) void runAllTests() {} dlopen passes, dlsym fails. Andrei
Dec 26 2016
parent reply Vladimir Panteleev <thecybershadow.lists gmail.com> writes:
On Monday, 26 December 2016 at 20:19:52 UTC, Andrei Alexandrescu 
wrote:
 Yah, I'm trying this:
Your program works for me verbatim on GNU/Linux on x86_64. A more portable approach would be to instrument the modules at compile-time (e.g. by iterating the modules' members and constructing a static array), and using it at run-time.
 void main()
 {
     void *hndl = dlopen(null, 1);
     hndl !is null || assert(0);
     auto n = "runAllTests".ptr;//m.name ~ "" '\0';
Perhaps try a leading underscore for the mangled function name. Not sure how things are different on OS X.
     auto p = cast(void function()) dlsym(hndl, n);
This will use the wrong calling convention. You need to cast to an extern(C) function pointer.
Dec 26 2016
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/26/2016 04:39 PM, Vladimir Panteleev wrote:
 On Monday, 26 December 2016 at 20:19:52 UTC, Andrei Alexandrescu wrote:
 Yah, I'm trying this:
Your program works for me verbatim on GNU/Linux on x86_64.
Thanks for the info. Interesting. I'm on Linux Mint building with dmd flag free. I just updated all of dmd, druntime, and phobos to the latest and greatest.
 A more portable approach would be to instrument the modules at
 compile-time (e.g. by iterating the modules' members and constructing a
 static array), and using it at run-time.
You still need to fetch the static array address. Essentially what I'm looking for is, starting from ModuleInfo, get to the address of something tangible that is planted intentionally (so I know its name). What is a good way to achieve that?
 void main()
 {
     void *hndl = dlopen(null, 1);
     hndl !is null || assert(0);
     auto n = "runAllTests".ptr;//m.name ~ "" '\0';
Perhaps try a leading underscore for the mangled function name. Not sure how things are different on OS X.
Yah, it's all Mint and according to objdump the name is runAllTests.
     auto p = cast(void function()) dlsym(hndl, n);
This will use the wrong calling convention. You need to cast to an extern(C) function pointer.
Thanks for saving me some head scratching later :o). Andrei
Dec 26 2016
parent reply Vladimir Panteleev <thecybershadow.lists gmail.com> writes:
On Monday, 26 December 2016 at 22:32:55 UTC, Andrei Alexandrescu 
wrote:
 You still need to fetch the static array address. Essentially 
 what I'm looking for is, starting from ModuleInfo, get to the 
 address of something tangible that is planted intentionally (so 
 I know its name). What is a good way to achieve that?
Have you already considered Object.factory?
Dec 26 2016
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/26/2016 05:35 PM, Vladimir Panteleev wrote:
 On Monday, 26 December 2016 at 22:32:55 UTC, Andrei Alexandrescu wrote:
 You still need to fetch the static array address. Essentially what I'm
 looking for is, starting from ModuleInfo, get to the address of
 something tangible that is planted intentionally (so I know its name).
 What is a good way to achieve that?
Have you already considered Object.factory?
It's what I'm trying to get rid of :o). -- Andrei
Dec 26 2016
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2016-12-26 22:39, Vladimir Panteleev wrote:

 Your program works for me verbatim on GNU/Linux on x86_64.
Works for me as well on macOS, no changes required. -- /Jacob Carlborg
Dec 27 2016
prev sibling parent Martin Nowak <code+news.digitalmars dawg.eu> writes:
On 12/26/2016 07:45 PM, Andrei Alexandrescu wrote:
 Say I have a module "a" that wants to call a function "void fun()" in
 another module "b". The name "b" is not known until runtime, i.e. it's
 read from the console. (Really the name is obtained by iterating foreach
 (m; ModuleInfo)).
 
 How do I get fun()'s address (or the null pointer if it doesn't exist)?
https://github.com/dlang/druntime/pull/617 Waiting to rectify the horrible Windows DLL implementation might not have been the best choice for that. Also Windows DLL is even stuck on fixing export, haven't heard from Benjamin Thaut since DConf. -Martin
Dec 26 2016