www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Dynamic load from another context

reply "Wolftein" <agustin.l.alvarez hotmail.com> writes:
I'm trying to design a plug-in system for my game, and i would 
like to share static members from both context (Application, 
Shared Library). I found out that i can get the address of a 
__gshared at compile time, so my question is, is it possible to 
build an associative array at compile-time?

What i'm trying to do is:

/// Template to get the address of a function.
template GetAddress(alias T)
{
     enum GetAddress = &T;
}

template DeclareAddress(alias T, string name)
{
     enum DeclareAddress = "__gshared " ~ T.stringof ~ " " ~ name;
}

Template RegisterAddress(alias T)
{
     addToAssociativeArray!(GetAddress!T);
}

mixin( DeclareAddress!(uint, shared_uint) );
RegisterAddress!(shared_uint);

Then i could register some shared variables like events and when 
the plug-in is loaded, iterate over that array and set the 
correct values at runtime.
Oct 30 2013
parent "TheFlyingFiddle" <theflyingfiddle gmail.com> writes:
On Thursday, 31 October 2013 at 02:45:36 UTC, Wolftein wrote:
 so my question is, is it possible to build an associative array 
 at compile-time?
Yes, by using ctfe it's possible. like so: enum int[string] aa = createAA(); auto createAA() { int[string] aa; aa["hello"] = 1; aa["foo"] = 123; return aa; } unittest { static assert(aa["hello"] == 1); static assert(aa["foo"] == 123); }
 Then i could register some shared variables like events and 
 when the plug-in is loaded, iterate over that array and set the 
 correct values at runtime.
This is not a good idea. The address values of functions/variables in a dll changes depending on where in memory the dll gets loaded. Since the addresses are determined at runtime compiletime calculations will not be correct. Also you could use the export keyword. This makes it possible to load the variables at runtime using the core.runtime module. However there seems to be problems with the export keyword see the DIP45 http://wiki.dlang.org/DIP45 I'm currently developing a reflection library for use across DLL's. In it i've done something simillar to what you want to do. I use annotations to indicate if a variable is sharable across dlls and then the code to handle the sharing is generated from those annotations via a mixin template. So bascialy i do something like this: (Simplified version) //Pluggin.d DLLShared __gshared size_t foo; DLLShared void bar(string a) { //Do something cool. } //Does not get shared over dll. void baz() { } mixin RegisterReflection; This would be expanded into something like this. __gshared void*[string] __reflectionData; export extern(C) void*[string] getReflectionTable() { return __reflectionData; } static this() { __reflectionData["foo"] = &foo; __reflectionData["bar"] = &bar; } //MainApp. alias extern(C) void function() reflection_pt; void main() { auto pluggin = loadPluggin("some_pluggin.dll"); auto data = pluggin.findFunc!(reflection_pt) ("getReflectionTable")(); auto fooPtr = cast(size_t*)(data["foo"]); //do something with the foo value. } I got a little sidetracked at the end. Hope this helped.
Oct 31 2013