我有一个Blah.cs:
public unsafe static int Main()
{
int[] ai = {1, 2, 3, 4, 5};
UIntPtr stai = (UIntPtr) ai.Length;
CManagedStuff obj = new CManagedStuff();
obj.DoSomething(ai, stai);
}
然后是ManagedStuff.cpp:
void CManagedStuff::DoSomething(int^ _ai, UIntPtr _stai)
{
// Here I should do something to marshal the int^ to an int*
pUnmanagedStuff->DoSomething(_ai, (size_t) _stai);
}
UnmanagedStuff.cpp:
void CUnmanagedStuff::DoSomething(int* _ai, size_t _stai)
{
// Walk and print the _stai ints in _ai
}
如何将int[] ai
从Main传递给ManagedStuff :: DoSomething?我知道该电话中没有编组,因为所涉及的所有代码都是管理的。
然后我如何在ManagedStuff :: DoSomething中编组int^ _ai
来调用UnmanagedStuff :: DoSomething?如果我在答案中有int[] _ai
这个问题可能会有所帮助(C#: Marshalling a "pointer to an int array" from a SendMessage() lParam)。
或者,我怎样才能避免使用C#,C ++互操作,微软和Windows,并阻止世界的痛苦?
答案 0 :(得分:2)
我只需要指出原始想法是多么破碎。
在本机代码中,您可以通过传递第一个元素的地址来传递数组,因为可以通过指针算法找到相邻的元素。
在托管代码中,元素也相邻存储,但是传递int^
框元素,在数组外部复制。此副本不会在附近存储任何其他数组元素。
事实上,这也发生在本机跨进程通信中。使用指针算法查找其他元素的技巧仅适用于进程,通常不适用。
答案 1 :(得分:1)
您必须固定托管资源(您的阵列),因此垃圾收集器在您使用指针时不会移动它。
在C#中,您可以使用fixed
语句执行此操作:fixed Statement (C# Reference)
在C ++中固定可以固定指针,当它们在范围内时会固定一个托管对象。 (指向任何元素的指针将固定整个数组):
// In CManagedStuff:
pin_ptr<int> _aiPinned = _ai
更多信息:C++/CLI in Action - Using interior and pinning pointers
答案 2 :(得分:1)
好的,我的工作方式是这样的:
void CManagedStuff::DoSomething(array<int>^ _ai, UIntPtr _stai)
{
// Here I should do something to marshal the int^ to an int*
pin_ptr<int> _aiPinned = &_ai[0];
pUnmanagedStuff->DoSomething(_aiPinned, (size_t) _stai);
}
首先,传递array<int>^
其次,正如Tamschi建议的那样,使用指针指向数组中第一个元素的地址。