非托管/托管互操作 - 麻烦传递int []

时间:2009-01-31 10:34:09

标签: c# interop unmanaged marshalling managed

我正在攻读化学博士学位,因此我需要编写一个软件应用程序来帮助我在显微镜下对样本进行成像。该显微镜配有x-y-z纳米定位台。使用由硬件供应商用VC ++编写的非托管DLL来控制阶段。我可以为您提供所需的更多细节,但让我从这开始;

dll中的一种方法允许我读取运动轴的设置:

C ++语法:

BOOL E7XX_qSVO (int ID, const char* szAxes, BOOL* pbValueArray) 

根据惯例,BOOL为int 0或1。

我的C#包装器包含:

[DllImport("E7XX_GCS_DLL.dll", EntryPoint = "E7XX_qSVO")]   
public static extern int qSVO(int iId, string sAxes, int []iValArray);

这对我来说似乎是正确的。但是当我在我的主应用程序中尝试这样的东西时(查询轴1,2和3):

Int32 [] _iValues = new Int32[3];
E7XXController.qSVO(m_iControllerID, "123", _iValues);

我一直得到这样的数组:

{6,0,10},而我应该根据设备本身的显示得到{0,0,0}。补充功能:

BOOL E7XX_SVO (int ID, const char* szAxes, const BOOL* pbValueArray)在舞台上设置相同的状态位也不起作用...

dll中的其他命令工作正常。我可以毫无困难地传递字符串和双打,但不是BOOL类型...

你们有什么想法可能有什么不对吗?

4 个答案:

答案 0 :(得分:1)

C ++中的BOOL实际上是一个“int”,因此请确保使用System.Int32而不是System.Boolean。 或者它可能使用COM数据类型,即VARIANT_BOOL,在这种情况下,您需要确实需要System.Boolean。 您是否尝试运行依赖关系查看器来确认函数原型?

答案 1 :(得分:1)

您是否尝试过指定MarshalAs属性,例如: -

[DllImport("E7XX_GCS_DLL.dll", EntryPoint = "E7XX_qSVO")]   
public static extern int qSVO(int iId, 
                              [MarshalAs(UnmanagedType.AnsiBStr)]string sAxes, 
                              [MarshalAs(UnmanagedType.LPArray)]int[] iValArray);

另外,您是否尝试将sAxes字符串作为字符串数组传递,例如: -

[DllImport("E7XX_GCS_DLL.dll", EntryPoint = "E7XX_qSVO")]   
public static extern int qSVO(int iId, 
                              [MarshalAs(UnmanagedType.LPArray)]char[] sAxes, 
                              [MarshalAs(UnmanagedType.LPArray)]int[] iValArray);

我发现使用互操作你经常需要尝试一下才能使它工作,所以尝试不同的组合,检查UnmanagedType枚举的不同成员,并也与其他人的建议一起玩。但是,请尝试以上两种技术,让我知道他们是否帮助排序!

答案 2 :(得分:0)

这不会直接回答你的问题,但是使用Pinvoke.net轻松获得常见的Interop Win32调用的一个很好的工具甚至还有一个Visual Studio插件。

http://www.pinvoke.net/index.aspx

答案 3 :(得分:0)

docs for your function说:

  

VC ++编译器需要一个extern“C”修饰符。声明还必须指定像标准Win-API函数一样调用这些函数。这意味着VC ++编译器需要在声明中看到WINAPI或__stdcall修饰符。

DllImport的默认调用约定是 WinApi 。在Windows上,这是StdCall。但在CE上,那就是Cdecl。您希望确保使用正确的调用约定。你可能想要托盘添加:

CallConvention = CallingConvention.StdCall

另外,请指定我们的字符串字符集:

CharSet = CharSet.Ansi

但即使没有这些也应该有效。你的代码看起来很正常,这很奇怪。

相关问题