Closed6
D言語でプラグインシステム
extern (C)
について
Note that extern(C) can be provided for all types of declarations, including struct or class, even though there is no corresponding match on the C side.
とあるようにCにない機能を含むシグネチャを持つ関数に対して extern (C)
しても問題ない。
extern(C)
すると、オブジェクトファイル上のシンボル名から、関数名以外の要素が消える。 extern(C++)
ではオーバーロードがあるためもう少し複雑だが、コンパイラ依存なので使わない方が良さそう。
module lib;
class Foo {}
Foo hello() { return new Foo(); }
extern (C) Foo hello() { return new Foo(); }
extern (C++) Foo hello() { return new Foo(); }
$ ldc2 -c lib.d
$ nm lib.o -C | ddemangle
U TypeInfo_Class.__vtbl
0000000000000000 V lib.__moduleRef
0000000000000000 D lib.__ModuleInfo
0000000000000000 D lib.Foo.__init
0000000000000000 D lib.Foo.__vtbl
0000000000000000 D lib.Foo.__Class
0000000000000000 T lib.Foo lib.hello()
U int object.Object.opCmp(Object)
U nothrow @trusted ulong object.Object.toHash()
U bool object.Object.opEquals(Object)
U immutable(char)[] object.Object.toString()
U Object.__Class
U _d_allocclass
0000000000000000 T hello
0000000000000000 T hello()
プラグインシステムの最小構成。
module plugin_a;
extern (C) int calc(int a, int b) { return a + b; }
module app;
import core.sys.posix.dlfcn;
void main() {
auto lh = dlopen("./libplugin_a.so", RTLD_LAZY);
if (!lh) { /* error handling */ }
auto calc = cast(int function(int, int)) dlsym(lh, "calc");
if (auto err = dlerror()) { /* error handling */ }
auto result = calc(1, 2);
dlclose(lh);
}
ldc2 plugin_a.d -shared
ldc2 app.d
./app
interface
を API とする例。
api.d
module api;
interface API {
int calc(int a, int b);
}
plugin_a.d
module plugin_a;
import api;
class PluginA : API {
int calc(int a, int b) { return a + b; }
}
extern(C) API create() {
return new PluginA();
}
app.d
import core.sys.posix.dlfcn;
import api;
void main() {
auto lh = dlopen("./libplugin_a.so", RTLD_LAZY);
if (!lh) { /* error handling */ }
auto create = cast(API function()) dlsym(lh, "create");
if (auto err = dlerror()) { /* error handling */ }
auto api = create();
auto result = api.calc(1,2);
dlclose(lh);
}
ldc2 plugin_a.d api.d -shared
ldc2 app.d
./app
このスクラップは2022/08/21にクローズされました