我是 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
);
这是基于此建议。
现在我需要从 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 的内容。
我希望有人能理解这一点并提供答案,或者至少为我指明正确的方向。