我有一个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
,那么这个SO问题答案中的代码可能会有所帮助(C#: Marshalling a "pointer to an int array" from a SendMessage() lParam)。
或者,我如何避免使用C#,C++互操作,微软和视窗,并停止世界的痛苦?
发布于 2011-05-25 23:20:56
好的,我让它像这样工作:
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所建议的,使用引脚指针指向数组中第一个元素的地址。
发布于 2011-05-27 00:55:30
我只需要指出最初的想法是多么地破碎。
在本机代码中,可以通过传递第一个元素的地址来传递数组,因为可以通过指针算法找到相邻的元素。
在托管代码中,元素也是相邻存储的,但传递int^
会将元素装箱,并在数组外部创建一个副本。此副本附近不会存储任何其他数组元素。
事实上,这也发生在本机跨进程通信中。使用指针算法查找其他元素的技巧仅适用于进程内,并且不适用于一般情况。
发布于 2011-05-25 20:09:26
您必须固定托管资源(您的数组),以便垃圾收集器在您使用指针时不会移动它。
在C#中,可以使用fixed
语句执行此操作:fixed Statement (C# Reference)
C++中的固定与固定指针一起工作,当托管对象在作用域中时,指针固定托管对象。(指向任何元素的指针将锁定整个数组):
// In CManagedStuff:
pin_ptr<int> _aiPinned = _ai
更多信息:C++/CLI in Action - Using interior and pinning pointers
https://stackoverflow.com/questions/6123335
复制相似问题