从D调用C#程序

从D调用C#程序,d,unmanaged,D,Unmanaged,如何从D调用C#函数(DLL) 我已经尝试或正在研究以下内容: 使用废弃的Mono软件包 () 使用非托管导出(请参见 ),D 到C到C#,最终可能消除C 被抛弃的Mono方法对于Hello World程序很有效,但是一个较大的DLL(引用了许多其他程序集,每个程序集可能使用或可能不使用真正的Windows API调用)会失败,因为DLL没有正确加载 使用非托管导出的初始实验导致MSBudio.< /P> < P>错误。我根据以下文章将一个从Robert Giesecke到(少量)C++的初

如何从D调用C#函数(DLL)

我已经尝试或正在研究以下内容:

  • 使用废弃的Mono软件包 ()

  • 使用非托管导出(请参见
    ),D 到C到C#,最终可能消除C

被抛弃的Mono方法对于Hello World程序很有效,但是一个较大的DLL(引用了许多其他程序集,每个程序集可能使用或可能不使用真正的Windows API调用)会失败,因为DLL没有正确加载


使用非托管导出的初始实验导致MSBudio.< /P> < P>错误。我根据以下文章将一个从Robert Giesecke到(少量)C++的初步字符串传递解决方案:(我放弃了来自非托管出口的) (汉斯·帕桑的教程)

< d + C++与Visual D的集成只是工作。

(请参见Visual C/C++项目集成)


尝试以下方法。首先是D代码:

module main;
import std.stdio;
import std.conv;

extern (C++) ulong receiveMe(ulong i);
extern (C++) ulong freeMe(ulong i);

void main() {
    ulong l = receiveMe(0);
    char* p = cast(char*)l;
    char[] s = to!(char[])(p);
    byte[] b = cast(byte[])(s.dup);
    writeln("The answer is " ~ to!string(s));
    ulong m = freeMe(0);
}
然后是一个C++/CLI垫片:

#include "stdafx.h"
#using "...\CS-Interop\bin\x64\Debug\netstandard2.0\CS-Interop.dll"

using namespace System;

UInt64 sendMe(UInt64 arg) {
    return CS_Interop::Test::receiveMe(42);
}

UInt64 freeMe(UInt64 arg) {
    return CS_Interop::Test::freeMe(42);
}
最后,C#:

我仍在寻找摆脱C++/CLI垫片的方法

这段代码的编写方式使您可以使用VS调试器进行调试

在VisualStudio中进行设置和测试非常简单。在VisualD安装后,首先设置一个C++/CLI项目(不是Visual D项目),并将D和C++代码停放在那里。然后在D项目下设置一个C#DLL项目

从D调用C#代码是一回事,但要获取数据又是另一回事,除非您只使用像int这样的简单标量类型

你首先需要把你要发送的东西输入到D.然后把地址发送到D。在C++部分中没有编排的冗长的混乱,你的D代码只需要处理指针后面的任何东西。 完成固定指针后,请确保将其释放。注释掉D代码中的freeMe行,观察VS中内存使用量的增长

就我个人而言,我发现pin进程有点易变,因为
GCHandle.Alloc
只有在其第一个参数(无论是字节数组还是结构)包含blittable项时才起作用


另请参见

您可以使用非托管导出从D调用C#。我这样做没有问题

然而,当我尝试使用Visual Studio 2017进行非托管导出时,我也无法使其正常工作。非托管导出与VS2015配合良好。考虑到这一联系始于2009年7月,其他方面可能已经过时


请务必仔细阅读说明,最重要的是确保您构建的是x86或x64,而不是“任何CPU”。整理数据将是另一项挑战。

谢谢。经过一些改变,这对我来说非常有效。
using System.Runtime.InteropServices;
using System.Text;

namespace CS_Interop {

    public class Test {

        public static byte[] buffer;

        public static GCHandle gcbuf;

        public static ulong receiveMe(ulong arg) {
            string s = "I was a string " + arg;
            s = (s.Length + 2) + s;
            buffer = Encoding.ASCII.GetBytes(s);
            gcbuf = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            ulong l = (ulong)gcbuf.AddrOfPinnedObject();
            return l;
        }

        public static ulong freeMe(ulong arg) {
            gcbuf.Free();
            return 42;
        }
    }
}
gcbuf = GCHandle.Alloc(buffer, GCHandleType.Pinned);
ulong l = (ulong)gcbuf.AddrOfPinnedObject();