是否可以从 C# 项目中引用 C++ 项目?
Is it possible to reference a C++ project from a C# project?
我正在尝试调用一些我从某些 C#(也是我的代码)编写的 C++,但在 Interop/PInvoke 获取已填充的 int[]
方面遇到了麻烦。有没有一种方法可以从 C# 项目添加对 C++ 项目的编译时引用并调用其中的函数,就像它只是另一个 C# class 库一样?
我有一个基本示例来说明数组的问题。这是我正在调用的 C++ 函数的 C# 签名。
[DllImport("CPlusPlusTargetLibrary.dll", CallingConvention = CallingConvention.StdCall)]
private static extern void Accumulate
(
int input,
int accumulationFactor,
int numberOfAccumulations,
[In, Out, MarshalAs(UnmanagedType.LPArray)]
int[] accumulationsPointer
);
这是从 C# 调用它的方式:
var numberOfAccumulations = 3;
var accumulations = new int[numberOfAccumulations];
Accumulate(-8, 1, numberOfAccumulations, accumulations);
这是它在C++头文件中的声明:
__declspec(dllexport) const void __stdcall Accumulate
(
const signed long input,
const signed long accumulationFactor,
const signed long numberOfAccumulations,
signed long* accumulationsPointer
);
这是它在 C++ 中的实现:
__declspec(dllexport) const void __stdcall Accumulate
(
const signed long input,
const signed long accumulationFactor,
const signed long numberOfAccumulations,
signed long* accumulationsPointer
)
{
for (auto index = 0; index < numberOfAccumulations; index++, accumulationsPointer++)
{
auto accumulation = input * ((index + 1) * accumulationFactor);
accumulationsPointer = &accumulation;
}
}
accumulations
数组作为所有 0
的 3 元素数组返回 - 就像它被传入一样。相反,它应该包含 -8
、-16
和 -24
.
我按照 MSDN 上的文档进行封送处理 int[]
,根据它,我不需要任何手动封送处理(但即使删除 MarshalAs
属性也没有解决问题): https://docs.microsoft.com/en-us/dotnet/framework/interop/marshaling-different-types-of-arrays
我曾希望如果我可以直接引用 C++ 项目,那么我就不必处理所有与类型相关的运行时故障。
您的代码不会写入 accumulationsPointer
的内容,而是用 accumulation
的地址覆盖指针本身
应该是这样的
for (auto index = 0; index < numberOfAccumulations; index++, accumulationsPointer++)
{
auto accumulation = input * ((index + 1) * accumulationFactor);
*accumulationsPointer = accumulation;
}
或者像这样,比如 c#
for (auto index = 0; index < numberOfAccumulations; ++index)
{
auto accumulation = input * ((index + 1) * accumulationFactor);
accumulationsPointer[index] = accumulation;
}
顺便说一句,signed long* accumulationsPointer
也可以写成signed long accumulationsPointer[]
,例如
void Accumulate
(
const signed long input,
const signed long accumulationFactor,
const signed long numberOfAccumulations,
signed long accumulations[]
)
{
for (auto index = 0; index < numberOfAccumulations; ++index)
{
auto accumulation = input * ((index + 1) * accumulationFactor);
accumulations[index] = accumulation;
}
}
我正在尝试调用一些我从某些 C#(也是我的代码)编写的 C++,但在 Interop/PInvoke 获取已填充的 int[]
方面遇到了麻烦。有没有一种方法可以从 C# 项目添加对 C++ 项目的编译时引用并调用其中的函数,就像它只是另一个 C# class 库一样?
我有一个基本示例来说明数组的问题。这是我正在调用的 C++ 函数的 C# 签名。
[DllImport("CPlusPlusTargetLibrary.dll", CallingConvention = CallingConvention.StdCall)]
private static extern void Accumulate
(
int input,
int accumulationFactor,
int numberOfAccumulations,
[In, Out, MarshalAs(UnmanagedType.LPArray)]
int[] accumulationsPointer
);
这是从 C# 调用它的方式:
var numberOfAccumulations = 3;
var accumulations = new int[numberOfAccumulations];
Accumulate(-8, 1, numberOfAccumulations, accumulations);
这是它在C++头文件中的声明:
__declspec(dllexport) const void __stdcall Accumulate
(
const signed long input,
const signed long accumulationFactor,
const signed long numberOfAccumulations,
signed long* accumulationsPointer
);
这是它在 C++ 中的实现:
__declspec(dllexport) const void __stdcall Accumulate
(
const signed long input,
const signed long accumulationFactor,
const signed long numberOfAccumulations,
signed long* accumulationsPointer
)
{
for (auto index = 0; index < numberOfAccumulations; index++, accumulationsPointer++)
{
auto accumulation = input * ((index + 1) * accumulationFactor);
accumulationsPointer = &accumulation;
}
}
accumulations
数组作为所有 0
的 3 元素数组返回 - 就像它被传入一样。相反,它应该包含 -8
、-16
和 -24
.
我按照 MSDN 上的文档进行封送处理 int[]
,根据它,我不需要任何手动封送处理(但即使删除 MarshalAs
属性也没有解决问题): https://docs.microsoft.com/en-us/dotnet/framework/interop/marshaling-different-types-of-arrays
我曾希望如果我可以直接引用 C++ 项目,那么我就不必处理所有与类型相关的运行时故障。
您的代码不会写入 accumulationsPointer
的内容,而是用 accumulation
应该是这样的
for (auto index = 0; index < numberOfAccumulations; index++, accumulationsPointer++)
{
auto accumulation = input * ((index + 1) * accumulationFactor);
*accumulationsPointer = accumulation;
}
或者像这样,比如 c#
for (auto index = 0; index < numberOfAccumulations; ++index)
{
auto accumulation = input * ((index + 1) * accumulationFactor);
accumulationsPointer[index] = accumulation;
}
顺便说一句,signed long* accumulationsPointer
也可以写成signed long accumulationsPointer[]
,例如
void Accumulate
(
const signed long input,
const signed long accumulationFactor,
const signed long numberOfAccumulations,
signed long accumulations[]
)
{
for (auto index = 0; index < numberOfAccumulations; ++index)
{
auto accumulation = input * ((index + 1) * accumulationFactor);
accumulations[index] = accumulation;
}
}