从 D 调用 C# 程序
Calling C# programs from D
如何从 D 调用 C# 函数(DLL)?
我已经尝试或正在查看以下内容:
使用废弃的 Mono 包
(https://github.com/kubasz/derelict-mono)
使用非托管导出(参见
Calling C# from C), D
从 C 到 C#,最终可能会消除 C.
Derelict Mono 方法适用于 Hello World 程序,但是更大的 DLL(引用许多其他程序集,每个程序集可能会或可能不会使用真正的 Windows API 调用)由于 DLL 未正确加载而失败。
使用非托管导出的初始实验导致 MSBUILD 出错。
基于以下文章,我有一个从 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(参见可视化 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 shim:
#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 shim 的方法。
此代码的编写方式使您可以使用 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();
你首先需要pin你要发回的东西,然后把地址发回D。在C++部分,你的D没有乏味的封送处理代码只需要能够处理指针后面的任何内容。
请务必在完成后释放固定指针。注释掉 D 代码中的 freeMe 行,观察 VS 中内存使用量的增长(和增长)。
就我个人而言,我发现 pin 过程有点善变,因为 GCHandle.Alloc
仅在其第一个参数(字节数组或结构)包含 blittable 项。
另见 https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types
您可以使用 Unmanaged Exports 从 D 调用 C#。我已经成功完成了。
见https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports
但是,当我尝试使用 Visual Studio 2017 进行非托管导出时,我也无法使其正常工作。非托管导出与 VS2015 配合良好。考虑到 link 是从 2009 年 7 月开始的,其他方面可能已经过时了。
请务必仔细阅读说明,最重要的是确保您构建的是 x86 或 x64,而不是 "any CPU"。整理数据将是另一个挑战。
如何从 D 调用 C# 函数(DLL)?
我已经尝试或正在查看以下内容:
使用废弃的 Mono 包 (https://github.com/kubasz/derelict-mono)
使用非托管导出(参见
Calling C# from C), D 从 C 到 C#,最终可能会消除 C.
Derelict Mono 方法适用于 Hello World 程序,但是更大的 DLL(引用许多其他程序集,每个程序集可能会或可能不会使用真正的 Windows API 调用)由于 DLL 未正确加载而失败。
使用非托管导出的初始实验导致 MSBUILD 出错。
基于以下文章,我有一个从 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(参见可视化 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 shim:
#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 shim 的方法。
此代码的编写方式使您可以使用 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();
你首先需要pin你要发回的东西,然后把地址发回D。在C++部分,你的D没有乏味的封送处理代码只需要能够处理指针后面的任何内容。
请务必在完成后释放固定指针。注释掉 D 代码中的 freeMe 行,观察 VS 中内存使用量的增长(和增长)。
就我个人而言,我发现 pin 过程有点善变,因为 GCHandle.Alloc
仅在其第一个参数(字节数组或结构)包含 blittable 项。
另见 https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types
您可以使用 Unmanaged Exports 从 D 调用 C#。我已经成功完成了。
见https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports
但是,当我尝试使用 Visual Studio 2017 进行非托管导出时,我也无法使其正常工作。非托管导出与 VS2015 配合良好。考虑到 link 是从 2009 年 7 月开始的,其他方面可能已经过时了。
请务必仔细阅读说明,最重要的是确保您构建的是 x86 或 x64,而不是 "any CPU"。整理数据将是另一个挑战。