如何从D调用C#函数(DLL)?
我尝试过或正在查看以下内容:
使用废弃的Mono软件包 (https://github.com/kubasz/derelict-mono)
使用非托管导出(请参阅
Calling C# from C),D
从C到C#,最终可能消除了C。
Derelict Mono方法对于Hello World程序效果很好,但是由于未正确加载DLL,因此较大的DLL(引用了很多其他程序集,其中每个程序集可能使用也可能不使用正版Windows API调用)失败。 / p>
使用非托管导出的初始实验会导致MSBUILD错误。
答案 0 :(得分:1)
基于以下文章,我有一个初步的字符串传递解决方案,从D到(少量)C ++到C#:(我放弃了Robert Giesecke的非托管输出)
C# "Unmanaged Exports"(Hans Passant的教程)
Calling C# function from C++/CLI - Convert Return C# string to C String
D到C ++与Visual D的集成就可以了。
https://rainers.github.io/visuald/visuald/vcxproject.html(请参阅Visual C / C ++项目集成)
答案 1 :(得分:1)
尝试以下方法。首先是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#:
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;
}
}
}
我仍在寻找摆脱C ++ / CLI填充程序的方法。
此代码的编写方式使您可以使用VS调试器进行调试。
这在Visual Studio中设置和测试非常简单。安装Visual D后,首先设置一个C ++ / CLI项目(不是Visual D项目),然后将D和C ++代码停在那里。然后在D项目下设置一个C#DLL项目。
从D调用C#代码是一回事,而另一回事情是取回数据,除非您仅使用int之类的简单标量类型。 C#的关键行是
gcbuf = GCHandle.Alloc(buffer, GCHandleType.Pinned);
ulong l = (ulong)gcbuf.AddrOfPinnedObject();
首先需要固定发送回的东西,然后再将地址发送回D。在C ++部分中,处理封送没有繁琐的事情,您的D代码只需要能够处理指针后面的任何东西。
完成操作后,还请确保释放固定的指针。注释掉D代码中的freeMe行,并观察VS中的内存使用量增长(和增长)。
我个人认为 pin 进程有些变幻,因为GCHandle.Alloc
仅在其第一个参数(字节数组或结构)包含 blittable时才有效 项。
另请参阅https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types
答案 2 :(得分:1)
您可以使用非托管导出从D调用C#。我已经做到了,没有问题。
请参见https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports
但是,当我尝试使用Visual Studio 2017进行非托管导出时,我也无法使其正常工作。非托管导出与VS2015配合良好。考虑到链接是从2009年7月开始的,其他方面可能已经过时。
请务必仔细阅读说明,最重要的是,请确保您要针对x86或x64而不是“任何CPU”进行编译。整理数据将是另一个挑战。