c# - 与 D 交互 正确返回一个结构数组

标签 c# pointers interop d

这个问题指的是"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# 调用它,没有尝试使用 CC++

旁注,除非您知道自己在做什么,否则请勿触摸任何现有代码。

所以下面的代码按预期工作

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/

相关文章:

c# - System.IO.Directory.Exists() 与 Windows 和 Linux 一起使用

c# - Unity - 来自 Sprite 顶点的网格

c++ - 关于使用指针访问 3D 数组的元素

c++ - 分配结构包括指针

.net - Excel COM 互操作 - tlbimp 与主要 WrapperTool

c# - 有没有简单的方法来制作 ScrollViewer "bouncy"?

c# - 可空 boolean 作为 C# 中的三态变量

c - 为什么解引用与 malloc 的行为不同?

c# - 从 C# 调用某些 Excel VBA 宏时出错

python - 通过已注册的 TLB 从 python 访问未注册的 COM 对象