这个问题指的是'新'D: DMD32 D编译器v2.068.2
表示TL; DR如果您不需要详细信息,请跳至下面的问题
使用visual studio(我正在使用v2010),创建new project
- > D
- > Dynamic Library
当项目creartion过程完成时,在解决方案资源管理器中 有两个文件:
保留.def
文件,我已经设法理解了这一点
通过向dllmain.d
添加一些新功能并优先使用:
extern (Windows) export
将导出该函数,并且可以从c#
调用,但不会使用C
或C++
进行调用。
旁注,除非您知道自己在做什么,否则请勿触摸任何现有代码。
所以下面的代码按预期工作
extern (Windows) export uint D_mathPower(uint p)
{
return p * p;
}
使用以下签名从C#调用它:
[DllImport(@"pathTo...\DynamicLib1.dll", CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurity]
public static extern uint D_mathPower(uint p);
我可以很容易地使用它如下:
uint powD = D_mathPower(5);
如何返回结构数组(最好是最具成本效益的方式)?
struct dpack{ char* Name; uint Id; }
我尝试过同时使用char[]
和char*
,但没有成功。
到目前为止这是我的代码
extern (Windows) export
dpack[] D_getPacks(uint size)
{
dpack[] rtDpArr = new dpack[size];
char[] str = "someText".dup;
for(uint i=0; i<size; i++)
{
str[$ - 1] = cast(char)('0' + i % (126 - '0'));
rtDpArr[i].Id = i;
rtDpArr[i].Name= str.dup;
}
return rtDpArr;
}
void getPacksPtr(uint size, dpack** DpArr)
{
// this is the signature i have successfully implemented via c++
}
答案 0 :(得分:1)
由于D数组具有特殊布局,因此您应该返回指向第一个项目的指针。然后在C#中,您可以通过读取每8个字节8个字节(这与dpack.sizeof
匹配)来从基指针转换每个项目,因为您已经知道了计数:
struct dpack{ immutable(char)* Name; uint Id; }
extern (Windows) export
void* D_getPacks(uint count)
{
dpack[] rtDpArr = new dpack[count];
char[] str = "someText".dup;
import std.string;
for(uint i=0; i<count; i++)
{
rtDpArr[i].Id = i;
// add a trailing '\0'
rtDpArr[i].Name = toStringz(str);
}
// pointer to the first item
return rtDpArr.ptr;
}
还要添加.Name
成员来添加终结符,否则你无法知道字符串的长度。这是由std.string.toStringz
完成的,它将在字符串的末尾添加一个空字符。然后可以将char* Name
成员转换为通常由具有C接口的dll中的函数提供的字符串。
答案 1 :(得分:0)
这是我实施它的最有效方式。
extern (Windows) export
void D_getPacksPtr(uint size, dpack** DpArr)
{
*DpArr = cast(dpack*) malloc(size * dpack.sizeof);
dpack* curP = *DpArr;
char[] str = "abcdefghij".dup;
uint i=0;
while(i!=size){
str[$ - 1] = cast(char)('0' + i % (126 - '0'));
curP.Name = cast(char*)str.dup; curP.Id = i;
++i;++curP;
}
}
[DllImport(@"PathTo...\DynamicLib1.dll", CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurity]
public static extern void D_getPacksPtr(uint size, dpack** DPArr);
使用它:
dpack* outDpack;
D_getPacksPtr(500000, &outDpack);