我试图理解这个"它只是工作" C#/ C ++互操作的神奇之处,但目前IT只是一个小问题。
我正在使用Mandelbrot计算,并希望将计算核心卸载到本机C ++和SSE2。这是有效的,P / Invoke。现在我想改为IJW,更加类型安全,因为我想了解它。但几十年前,当我抓住C ++的表面时。
我有一个struct Complex { double real; double imag; }
来保存Mandelbrot循环的起始值,我想调用这样的函数:
Compute(int vectorSize, Complex[] points, double maxValue, int maxLoops, int[] result)
现在我使用VS Express 2013创建了一个CLR类库,并将其放入一个头文件中:
public value struct Complex
{
double real;
double imag;
};
public ref class Computations
{
public:
static void Basic(int vectorSize, array<Complex,1>^ points, double maxRadius, int maxLoops, array<int,1>^ result);
};
class NativeComputations
{
public:
static void Basic(int vectorSize, Complex* points, double maxRadius, int maxLoops, int* result);
};
并在CPP文件中:
#pragma managed
void Mandelbrot::Computations::Basic(int vectorSize, array<Complex,1>^ points, double maxRadius, int maxLoops, array<int,1>^ result)
{
pin_ptr<Complex> pPoints = &points[0];
pin_ptr<int> pResult = &result[0];
NativeComputations::Basic(vectorSize, pPoints, maxRadius, maxLoops, pResult);
}
#pragma unmanaged
void Mandelbrot::NativeComputations::Basic(int vectorSize, Complex* points, double maxRadius, int maxLoops, int* result)
{
double foo = points[0].real;
}
此时我被卡住了 - 错误C3821:&#39;点&#39;:托管类型或功能无法在非托管功能中使用
所以我需要使用一些不受管理的东西。我可以重复我的代码并声明一个ComplexNative结构(通过省略&#34;值&#34;关键字)。这是可行的,但重复代码?即使这样,将Complex []转换为固定的ComplexNative *需要什么?
而且,请不要将结构拆分为double [] real,double [] imag。这可能会导致更简单的解决方法,但我想知道如何正确地做到这一点。
答案 0 :(得分:4)
这是托管代码的基石,托管编译器禁止对类型布局做出任何假设。只有这样,代码才能在不同的体系结构中实现可验证和类型安全。事实上,CLR会使用它,有意识地重新排序类型的成员,如果它产生更好的布局。
因此,托管的Complex结构不能转换为类似的NativeComplex,编译器根本无法假设这些类型在任何方面都是相同的。这迫使你复制数组,从array<Complex>
到NativeComplex[]
,一个元素和一个成员。
但是你没有使用pinvoke marshaller和复杂类型的编组,这不是C ++ Interop(又名IJW)的内置功能。你必须自己调用它:
void Mandelbrot::Computations::Basic(int vectorSize, array<Complex,1>^ points, double maxRadius, int maxLoops, array<int,1>^ result)
{
pin_ptr<Complex> pPoints = &points[0];
NativeComplex* pNative = (NativeComplex*)pPoints; // cheat
pin_ptr<int> pResult = &result[0];
NativeComputations::Basic(vectorSize, pNative, maxRadius, maxLoops, pResult);
}
哪个不漂亮,但你会侥幸逃脱,如果你想要快速代码,那么你必须这样做。请记住,这绝不是在所有情况下盲目地投射指针的认可。存在惊喜,一个很好的例子是this question。