这个问题指的是"new"D: DMD32 D 编译器 v2.068.2
for TL;DR if you don't need details skip to the question below
使用 visual studio(我使用的是 v2010),通过创建一个新项目
-> D
-> Dynamic Library
项目创建过程完成后,在解决方案资源管理器中 有 2 个文件:
- dllmain.d
- dll.def
按原样保留 .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++
}
最佳答案
因为 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 接口(interface)的 dll 中的函数提供的字符串。
关于c# - 与 D 交互 正确返回一个结构数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33481693/