Jump to page: 1 2
Thread overview
Pragma mangle and D shared objects
Oct 25, 2014
Etienne Cimon
Oct 25, 2014
H. S. Teoh
Oct 25, 2014
Etienne Cimon
Oct 25, 2014
Etienne Cimon
Oct 25, 2014
H. S. Teoh
Oct 25, 2014
John Colvin
Oct 26, 2014
H. S. Teoh
Oct 26, 2014
Etienne Cimon
Oct 26, 2014
H. S. Teoh
Oct 26, 2014
Etienne Cimon
Nov 06, 2014
Etienne Cimon
October 25, 2014
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.

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?

Also, I've never seen the thunkEBX change merged from here:

http://forum.dlang.org/thread/hznsrmviciaeirqkjzpy@forum.dlang.org?page=2#post-lg2lqi:241ga3:241:40digitalmars.com
October 25, 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.
October 25, 2014
That looks like exactly the solution I need, very clever. It'll take some time to wrap my head around it :-P
October 25, 2014
On 2014-10-25 11:56, Etienne Cimon wrote:
> That looks like exactly the solution I need, very clever. It'll take
> some time to wrap my head around it :-P

Just brainstorming here, but I think every dynamic library should hold a utility container (hash map?) that searches for and returns the mangled names in itself using regex match. This container would always be in the same module/function name in every dynamic library.

The mangling list would load itself using introspection through a `shared static this()`. For each module, for each class, insert mangling in the hashmap...

This seems ideal because then you basically have libraries that document themselves at runtime.

Of course, the return type and arguments would have to be decided in advance, but otherwise it allows loading and use of (possibly remote and unknown) DLLs, in a very simple way.
October 25, 2014
On Sat, Oct 25, 2014 at 12:15:19PM -0400, Etienne Cimon via Digitalmars-d-learn wrote:
> On 2014-10-25 11:56, Etienne Cimon wrote:
> >That looks like exactly the solution I need, very clever. It'll take some time to wrap my head around it :-P

It's not that complicated, really. It's basically putting together 3 things:

1) .mangleof to extract a mangled symbol from some function declaration
2) regex to replace the function name in the mangled symbol
3) compile-time introspection to build a function declaration out of a
   user-specified signature.


> Just brainstorming here, but I think every dynamic library should hold a utility container (hash map?) that searches for and returns the mangled names in itself using regex match. This container would always be in the same module/function name in every dynamic library.

Actually, the object file (library) itself should already have a list of exported symbols; you could then use core.demangle to extract the function signatures from the mangled symbols and construct a hash of all exported symbols and their types. The only thing is, I don't know of any cross-platform method of retrieving the list of exported symbols -- the Posix dlsym() family of functions only allow lookup by explicit symbol name, no iteration primitives are specified. But the information is definitely there, since that's how the OS's dynamic linker figures out how to link dynamic libraries in the first place!


[...]
> Of course, the return type and arguments would have to be decided in advance, but otherwise it allows loading and use of (possibly remote and unknown) DLLs, in a very simple way.

Well, generally, in order to make use of the functions in the first place, you'd need some kind of pre-determined return type and parameter types, otherwise the program couldn't possibly know how to pass arguments or interpret the return value!

But if you could extract the list of exported symbols from a library, then you could demangle them to determine their signatures, and thereby find all symbols matching some given signature.


T

-- 
Curiosity kills the cat. Moral: don't be the cat.
October 25, 2014
On Saturday, 25 October 2014 at 18:40:23 UTC, H. S. Teoh via Digitalmars-d-learn wrote:
> Actually, the object file (library) itself should already have a list of
> exported symbols; you could then use core.demangle to extract the
> function signatures from the mangled symbols and construct a hash of all
> exported symbols and their types. The only thing is, I don't know of any
> cross-platform method of retrieving the list of exported symbols -- the
> Posix dlsym() family of functions only allow lookup by explicit symbol
> name, no iteration primitives are specified. But the information is
> definitely there, since that's how the OS's dynamic linker figures out
> how to link dynamic libraries in the first place!
>
> T

I wonder what nm uses. AFAIK it works on everything posix.
October 26, 2014
On Sat, Oct 25, 2014 at 08:05:18PM +0000, John Colvin via Digitalmars-d-learn wrote:
> On Saturday, 25 October 2014 at 18:40:23 UTC, H. S. Teoh via Digitalmars-d-learn wrote:
> >Actually, the object file (library) itself should already have a list of exported symbols; you could then use core.demangle to extract the function signatures from the mangled symbols and construct a hash of all exported symbols and their types. The only thing is, I don't know of any cross-platform method of retrieving the list of exported symbols -- the Posix dlsym() family of functions only allow lookup by explicit symbol name, no iteration primitives are specified. But the information is definitely there, since that's how the OS's dynamic linker figures out how to link dynamic libraries in the first place!
> >
> >T
> 
> I wonder what nm uses. AFAIK it works on everything posix.

Not sure what nm uses, but a lot of posix tools for manipulating object files are based on binutils, which understands the local system's object file format and deal directly with the binary representation. The problem is, I don't know of any *standard* system functions that can do this, so you'd have to rely on OS-specific stuff to make it work, which is less than ideal.


T

-- 
Indifference will certainly be the downfall of mankind, but who cares? -- Miquel van Smoorenburg
October 26, 2014
On 2014-10-25 21:26, H. S. Teoh via Digitalmars-d-learn wrote:
> Not sure what nm uses, but a lot of posix tools for manipulating object
> files are based on binutils, which understands the local system's object
> file format and deal directly with the binary representation. The
> problem is, I don't know of any *standard* system functions that can do
> this, so you'd have to rely on OS-specific stuff to make it work, which
> is less than ideal.
>

Which makes it better to export the mangling into a container at compile-time! That way, you can build a standard interface into DLLs so that other D application know what they can call =)

October 26, 2014
On Sat, Oct 25, 2014 at 10:54:53PM -0400, Etienne Cimon via Digitalmars-d-learn wrote:
> On 2014-10-25 21:26, H. S. Teoh via Digitalmars-d-learn wrote:
> >Not sure what nm uses, but a lot of posix tools for manipulating object files are based on binutils, which understands the local system's object file format and deal directly with the binary representation. The problem is, I don't know of any *standard* system functions that can do this, so you'd have to rely on OS-specific stuff to make it work, which is less than ideal.
> >
> 
> Which makes it better to export the mangling into a container at compile-time! That way, you can build a standard interface into DLLs so that other D application know what they can call =)

Hmm. You can probably use __traits(getAllMembers...) to introspect a
library module at compile-time and build a hash based on that, so that
it's completely automated. If you have this available as a mixin, you
could just mixin(exportLibrarySymbols()) in your module to produce the
hash.


T

-- 
"Holy war is an oxymoron." -- Lazarus Long
October 26, 2014
On 2014-10-25 23:31, H. S. Teoh via Digitalmars-d-learn wrote:
> Hmm. You can probably use __traits(getAllMembers...) to introspect a
> library module at compile-time and build a hash based on that, so that
> it's completely automated. If you have this available as a mixin, you
> could just mixin(exportLibrarySymbols()) in your module to produce the
> hash.

Exactly, or I could also make it export specific functions into the hashmap, a little like a router. It seems like a very decent option.

« First   ‹ Prev
1 2