Pragma mangle and D shared objects
H. S. Teoh via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sat Oct 25 08:07:48 PDT 2014
On Sat, Oct 25, 2014 at 09:20:33AM -0400, Etienne Cimon via Digitalmars-d-learn wrote:
> I haven't been able to find much about pragma mangle. I'd like to do
> the following:
>
> http://forum.dlang.org/thread/hznsrmviciaeirqkjzpy@forum.dlang.org#post-zhxnqqubyudteycwudzz:40forum.dlang.org
>
> The part I find ugly is this:
>
> void* vp = dlsym(lib, "_D6plugin11getInstanceFZC2bc2Bc\0".ptr);
>
> I want to write a framework that stores a dynamic library name and
> symbol to execute, and downloads the dynamic library if it's not
> available. This would be in a long-running server/networking
> application, and needs to be simple to use.
Perhaps the .mangleof built-in property might help you here? For
instance:
---plugin.d---
class MyClass;
MyClass getInstance();
---test.d---
import std.stdio;
import plugin;
void main() {
writeln(plugin.getInstance.mangleof);
}
Output:
_D6plugin11getInstanceFZC6plugin7MyClass
Granted, it's a bit ugly (you have to actually create a module called
'plugin' in order to get the right mangling), but at least it doesn't
require the user to learn how D's mangling scheme works. You just write
a function prototype for the function you're trying to lookup, and call
.mangleof on it.
> The mangling makes it less obvious for the programmer writing a
> plugin. Does mangle make it possible to change this to dlsym(lib,
> "myOwnMangledName"), or would it still have strange symbols?
[...]
What you *could* do, is to use .mangleof and clever regex'ing to make it
possible to do that. For example, something along these lines:
---dl_support.d---
alias ReturnType = ... /* whatever type you want */;
private ReturnType pluginFuncStubName(... /* arguments here */);
auto loadPluginFunction(string library, string funcName) {
auto r = regex(`pluginFuncStubName`);
auto mangledName =
pluginFuncStubName.mangleof.replace(r, funcName);
...
/* mangledName should now be the mangled string you need
* to find the symbol */
}
Basically, use an unambiguous blatantly long name for your function
prototype, and do a search-and-replace to substitute that with the
desired function name.
Note that you still need to have a separate stub per function signature;
so if you want users to be able to load functions of arbitrary
signature, you probably need to make that a template parameter and have
the user pass in the desired function signature. For example:
auto loadPluginFunction(Signature)(string library, string funcName)
{
import std.traits : ReturnType, ParameterTypeTuple;
import std.regex : regex, replaceFirst;
// Declare a static function with the user-desired
// signature, with a nicely-substitutable name
static ReturnType!Signature
pluginFuncStubName(ParameterTypeTuple!Signature);
auto r = regex(`pluginFuncStubName`);
auto symbol = pluginFuncStubName.mangleof.replaceFirst(r, funcName);
// Proof of concept
import std.stdio;
writeln(symbol);
// ... Call dlsym to find function here
// Just to make this compile, replace with real function pointer in
// your code here.
return null;
}
void main() {
auto f1 = loadPluginFunction!(int function(string,int))("mylib", "func1");
auto f2 = loadPluginFunction!(void function(float))("mylib", "func2");
}
Output:
_D4test33__T18loadPluginFunctionTPFAyaiZiZ18loadPluginFunctionFAyaAyaZ18func1FAyaiZi
_D4test30__T18loadPluginFunctionTPFfZvZ18loadPluginFunctionFAyaAyaZ18func2FfZv
This example isn't complete yet (you need to do something about the
"loadPluginFunction" component in the mangled name), but you should be
able to work out a way of producing the correct mangled name from here.
But at least it demonstrates how you can have a very nice API for your
users -- they just pass in the function prototype of the function they
want, and the library code takes care of deriving the correct mangled
names.
Hope this helps.
T
--
Just because you can, doesn't mean you should.
More information about the Digitalmars-d-learn
mailing list