P / Invoke позже не знает, как распределить массивы в стиле C от неуправляемой к управляемой стороне;в отличие от SAFEARRAY
, в массивы в стиле C не встроена информация, которую P / Invoke позже сможет использовать для определения количества копируемых байтов.
Из-за этого вы 'Я захочу объявить вашу C
функцию для возврата IntPtr
, а затем вызвать Marshal.PtrToStrAnsi
метод для преобразования указателя в строку на управляемой стороне следующим образом:
[DllImport("library.dll")]
public static extern IntPtr C(int i);
static int Main()
{
int k = ABC(10);
IntPtr b = C(1024);
string s = Marshal.PtrToStrAnsi(b);
// Problem: How do you release what is pointed to
// by IntPtr?
return 0;
}
Кроме того, вам придется передать IntPtr
обратно на неуправляемую сторону, чтобы освободить память, выделенную вам new
;в противном случае у вас будет утечка памяти.
Более простой вариант - создать управляемую оболочку для вашей неуправляемой библиотеки на C ++, которая предоставляет управляемые функции, которые выполняют вызовы и выполняют преобразование в * 1020.* (используя marshal_as
) примерно так:
// compile with: /clr
#include <stdlib.h>
#include <string.h>
#include <memory>
#include <msclr\marshal.h>
using namespace System;
using namespace msclr::interop;
String^ WrappedC(int i) {
// Make the call to the native function.
// Let's store in an auto_ptr to handle
// cleanup when the wrapper is exited.
auto_ptr<char> c(C(i));
// Convert to a managed string and
// return.
return marshal_as<String^>(c.get());
}
Если вы не хотите маршалировать обратно string
, а вместо этого маршалировать обратно массив byte
, тогдаЯ бы по-прежнему рекомендовал подход обертки (хотя в этом случае он требует определенных знаний для создания возвращаемого управляемого массива):
// compile with: /clr
#include <stdlib.h>
#include <memory>
using namespace System;
using namespace msclr::interop;
String^ WrappedC(int i) {
// Make the call to the native function.
// Let's store in an auto_ptr to handle
// cleanup when the wrapper is exited.
auto_ptr<char> c(C(i));
// Copy the pointer.
char* p = c.get();
// The byte array to return.
// i is the size of the array, as per the call
// to C.
array<byte>^ a = gcnew array<byte>(i);
// Populate.
for (int index = 0; index < i; ++index)
a[index] = (byte) *p++;
// Return the array.
return a;
}
Это лучшие варианты, чем обрабатывать его вполностью управляемый код, так как вам не нужно беспокоиться о непрерывном распределении между управляемым и неуправляемым для обработки указателей на память, выделенную в неуправляемом пространстве.