AutoDLL
FoxyBrown via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Thu Jul 6 13:34:14 PDT 2017
Here is a solution that will wrap all extern C functions and
allow one to then map them to a dll.
auto BuildDLLClassFromCHeader(alias modulename, string name)()
{
import std.traits, std.algorithm, std.meta;
auto s = "extern (C) class " ~name~"\n{\n\timport ___import =
"~moduleName!modulename~";\n";
mixin("import "~moduleName!modulename~";");
foreach(m; AliasSeq!(__traits(allMembers, modulename)))
{
mixin("alias member = " ~ fullyQualifiedName!(modulename) ~ "."
~ m ~ ";");
static if (is(typeof(member) == function))
static if (functionLinkage!member != "C")
continue;
else
s ~= "\tpublic static typeof(___import."~__traits(identifier,
member)~")* "~__traits(identifier, member)~";\n";
}
return s ~ "}";
}
void DllImport(alias T)(string dllName)
{
import core.sys.windows.windows, std.conv, std.meta;
auto dll = LoadLibrary(to!wstring(dllName~"\0").ptr);
if (dll == null)
assert(0, "Cannot load DLL `"~dllName~"'");
foreach(fname; __traits(derivedMembers, T))
{
auto func = GetProcAddress(dll, fname);
enum s = "auto p = cast(void**)&"~T.stringof~"."~fname~"; *p =
cast(typeof(p))func;";
mixin(s);
}
}
e.g.,
mixin(BuildDLLClassFromCHeader!(portaudio, "PortAudioDLL")());
DllImport!PortAudioDLL("portaudio_x86.dll");
it generates the following for portaudio.di:
extern (C) class PortAudioDLL
{
import ___import = portaudio;
public static typeof(___import.Pa_GetVersion)* Pa_GetVersion;
public static typeof(___import.Pa_GetVersionText)*
Pa_GetVersionText;
public static typeof(___import.Pa_GetErrorText)* Pa_GetErrorText;
public static typeof(___import.Pa_Initialize)* Pa_Initialize;
public static typeof(___import.Pa_Terminate)* Pa_Terminate;
public static typeof(___import.Pa_GetHostApiCount)*
Pa_GetHostApiCount;
public static typeof(___import.Pa_GetDefaultHostApi)*
Pa_GetDefaultHostApi;
public static typeof(___import.Pa_GetHostApiInfo)*
Pa_GetHostApiInfo;
public static typeof(___import.Pa_HostApiTypeIdToHostApiIndex)*
Pa_HostApiTypeIdToHostApiIndex;
public static
typeof(___import.Pa_HostApiDeviceIndexToDeviceIndex)*
Pa_HostApiDeviceIndexToDeviceIndex;
public static typeof(___import.Pa_GetLastHostErrorInfo)*
Pa_GetLastHostErrorInfo;
public static typeof(___import.Pa_GetDeviceCount)*
Pa_GetDeviceCount;
public static typeof(___import.Pa_GetDefaultInputDevice)*
Pa_GetDefaultInputDevice;
public static typeof(___import.Pa_GetDefaultOutputDevice)*
Pa_GetDefaultOutputDevice;
public static typeof(___import.Pa_GetDeviceInfo)*
Pa_GetDeviceInfo;
public static typeof(___import.Pa_IsFormatSupported)*
Pa_IsFormatSupported;
public static typeof(___import.Pa_OpenStream)* Pa_OpenStream;
public static typeof(___import.Pa_OpenDefaultStream)*
Pa_OpenDefaultStream;
public static typeof(___import.Pa_CloseStream)* Pa_CloseStream;
public static typeof(___import.Pa_SetStreamFinishedCallback)*
Pa_SetStreamFinishedCallback;
public static typeof(___import.Pa_StartStream)* Pa_StartStream;
public static typeof(___import.Pa_StopStream)* Pa_StopStream;
public static typeof(___import.Pa_AbortStream)* Pa_AbortStream;
public static typeof(___import.Pa_IsStreamStopped)*
Pa_IsStreamStopped;
public static typeof(___import.Pa_IsStreamActive)*
Pa_IsStreamActive;
public static typeof(___import.Pa_GetStreamInfo)*
Pa_GetStreamInfo;
public static typeof(___import.Pa_GetStreamTime)*
Pa_GetStreamTime;
public static typeof(___import.Pa_GetStreamCpuLoad)*
Pa_GetStreamCpuLoad;
public static typeof(___import.Pa_ReadStream)* Pa_ReadStream;
public static typeof(___import.Pa_WriteStream)* Pa_WriteStream;
public static typeof(___import.Pa_GetStreamReadAvailable)*
Pa_GetStreamReadAvailable;
public static typeof(___import.Pa_GetStreamWriteAvailable)*
Pa_GetStreamWriteAvailable;
public static typeof(___import.Pa_GetSampleSize)*
Pa_GetSampleSize;
public static typeof(___import.Pa_Sleep)* Pa_Sleep;
}
and then maps the function pointers to the dll.
Should work for other dlls.
More information about the Digitalmars-d-learn
mailing list