Closed6

D言語でプラグインシステム

nonanonnononanonno

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) しても問題ない。

nonanonnononanonno
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()
nonanonnononanonno

プラグインシステムの最小構成。

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
nonanonnononanonno

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にクローズされました