Попробуйте следующее.Сначала код 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 ++.Затем настройте проект C # DLL в рамках проекта D.
Одно дело вызвать код C # из D, но другое - получить данные обратно, если вы не используете только простые скалярные типы, такие как int.Ключевыми строками C # являются
gcbuf = GCHandle.Alloc(buffer, GCHandleType.Pinned);
ulong l = (ulong)gcbuf.AddrOfPinnedObject();
, где вам сначала нужно закрепить вещь, которую вы отправляете обратно, а затем отправить адрес обратно D. Нет никакого утомительного хулиганства с маршалингом вчасть C ++, ваш D-код должен быть в состоянии справиться с тем, что находится за указателем.
Обязательно освободите закрепленный указатель, как только вы закончите с ним.Закомментируйте строку freeMe в D-коде и наблюдайте рост (и рост) использования памяти в VS.
Лично я нахожу процесс pin немного изменчивым, поскольку GCHandle.Alloc
будет работать только тогда, когда его первый аргумент, будь то байтовый массив или структура, содержит blittable предметов.
См. Также https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types