使用interop将一组int从C#传递到本机代码

时间:2011-05-25 10:55:44

标签: c# .net visual-c++ c++-cli interop

我有一个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,并阻止世界的痛苦?

3 个答案:

答案 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建议的那样,使用指针指向数组中第一个元素的地址。