如何将指针函数从C++导出到C#
How to export pointer function from C++ to C#?
我正在使用DllImport从C#调用C++的函数。
#if defined(__cplusplus)
extern "C" {
#endif
__declspec(dllexport) int __stdcall ABC(int i);
__declspec(dllexport) char* __stdcall C(int i);
#if defined(__cplusplus)
}
#endif
int __stdcall ABC(int i)
{
return i;
}
char* __stdcall C(int i)
{
char* n = new char[i];
memset(n, 9, i);
return n;
}
C#中的代码为:
using System.Runtime.InteropServices;
using System;
namespace DepartmentStore
{
class Exercise
{
[DllImport("library.dll")]
public static extern int ABC(int i);
[DllImport("library.dll")]
public static extern char* C(int i);
static int Main()
{
int k = ABC(10);
byte[] b = C(1024);
return 0;
}
}
}
函数ABC(int i)
正常,但函数C(int i)
在构建时产生以下错误:
"指针和固定大小的缓冲区只能在不安全的上下文中使用"
我想我不知道如何导出函数的指针返回。
有人能告诉我C#调用以返回类型为指针的函数的正确方式吗?
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++中为非托管库创建一个托管包装器,该包装器公开进行调用并执行转换为String^
(使用marshal_as
)的托管函数,如下所示:
// compile with: /clr
#include <stdlib.h>
#include <string.h>
#include <memory>
#include <msclrmarshal.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;
}
这些选项比完全在托管代码中处理要好,因为您不必担心在托管和非托管之间连续编组,以处理指向非托管空间中分配的内存的指针。
相关文章:
- 1d 智能指针不适用于语法 (*)++
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 为什么使用 "this" 指针调用派生成员函数?
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用指针从C++中的数组中获取最大值
- 助记符和指向成员语法的指针
- 嵌入方指针压缩已禁用
- 数组的指针从不分段故障
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 何时在引用或唯一指针上使用移动语义
- QMetaObject invokeMethod的基于函数指针的语法
- 如何从 std::atomic 中提取指针 T<T>?
- 如何在 C# 中映射双 C 结构指针?
- C++将浮点指针值舍入为小数位数
- 为什么++(*p)更改指针值
- 调整大小后指向元素值的指针unordered_map有效?
- 正在将指针转换为范围
- 使用指向成员的指针将成员函数作为参数传递
- 将OpenCV C++重写为EmguCV C#-如何使用指针
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错