【发布时间】:2013-03-28 00:49:29
【问题描述】:
我是 C# 新手,但我曾广泛使用 C++。我有一个需要从 C# 调用的 C++ 函数。在阅读了一些 SO 的答案和一些谷歌搜索后,我得出结论,我需要为该函数创建一个纯 C 接口。我已经这样做了,但仍然对如何从 C# 调用它感到困惑。
C++ 中的函数如下所示:
int processImages(
std::string& inputFilePath, // An input file
const std::vector<std::string>& inputListOfDirs, // Input list of dirs
std::vector<InternalStruct>& vecInternalStruct, // Input/Output struct
std::vector<std::vector< int > >& OutputIntsForEachFile,
std::vector< std::vector<SmallStruct> >& vecVecSmallStruct, // Output
int verboseLevel
);
同样的函数,用 C 语言转换,如下所示:
int processImagesC(
char* p_inputFilePath, // An input file
char** p_inputListOfDirs, // Input list of dirs
size_t* p_numInputDirs, // Indicating number of elements
InternalStruct* p_vecInternalStruct, // Input/Output struct
size_t* p_numInternalStructs,
int** p_OutputIntsForEachFile, // a 2d array each row ending with -1
size_t* p_numOutputIntsForEachFile //one number indicating its number of rows
SmallStruct** p_vecVecSmallStruct, // Output
size_t* p_numInVecSmallStruct,
int verboseLevel
);
这是基于this 的建议。
现在我需要从 C# 调用它,这就是混乱的地方。我已尽力转换结构。
C# 代码如下所示:
[DllImport(
@"C:\path\to\cppdll.dll", CallingConvention=CallingConvention.Cdecl,
EntryPoint="processImagesC", SetLastError=true)]
[return: MarshalAs(UnmanagedType.I4)]
unsafe public static extern int processImagesC(
String inputFilePath,
String[] inputListOfDirs,
ref uint numInputListOfDirs,
// Should I use ref InternalStruct * vecInternalStruct?
ref InternalStruct[] vecInternalStruct,
ref uint numInternalStruct,
// Or ref int[] or ref int[][] or int[][]?
ref int[][] OutputIntsForEachFile,
ref uint numOutputIntsForEachFile,
// again, ref ..[], [][], or ref [][]?
ref SmallStruct[][] vecVecSmallStruct,
int verboseLevel
);
在 C/C++ 代码中为所有输出变量(指针)分配内存。这可能意味着我们需要将代码声明为不安全,对吗?
我们如何处理内存释放?我是否应该编写另一个 API(函数)来释放 C/C++ 分配的对象/数组?
C++ 代码需要符合标准且独立于平台,因此我无法在其中插入任何特定于 Windows 的内容。
我希望有人能理解这一点并提供答案,或者至少为我指明正确的方向。
【问题讨论】:
-
你永远不应该从 C# 调用 C++。名称修饰格式在编译之间并不相同。
-
如果太复杂,您可以围绕原生 C++ 创建托管 C++/CLI 包装器,以便更轻松地从 C# 调用。
-
必须同意 C++/CLI 包装器方法。框架中有一些实用程序可以在 STL 类型之间进行转换。
-
@Romoku 你能解释一下我该如何创建这个托管的 C++/CLI 包装器吗?我没有使用托管 C++ 的经验...
-
C++/CLI 就是答案。
标签: c# c++ dll interop pinvoke