非托管/托管互操作 - 传递 int[] 时遇到问题

发布于 2024-07-13 04:29:30 字数 941 浏览 6 评论 0原文

我正在攻读化学博士学位,因此我需要编写一个软件应用程序来帮助我在显微镜下对样品进行成像。 该显微镜配有 xyz 纳米定位台。 该阶段使用硬件供应商用 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 类型...

你们知道可能出了什么问题吗?

I am working on my phd in chemistry and for that reason I need to write a software application to help me with the imaging of samples under a microscope. This microscope is fitted with an x-y-z nanopositioning stage. The stage is controlled using an unmanaged DLL written in VC++ by the hardware vendor. I could provide you with more specifics of needed but let me start with this;

One of the methods in the dll allows me to read settings for the axis of motion:

C++ syntax:

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

Where BOOL is int 0 or 1 according to the convention.

My C# wrapper contains:

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

This seems correct to me. However when I try something like this in my main application (to query axis 1,2 and 3):

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

I consistently get an array like this:

{6, 0, 10} while I should get {0, 0 , 0} according to the display on the device itself. The complementary function:

BOOL E7XX_SVO (int ID, const char* szAxes, const BOOL* pbValueArray) to set the same status bits on the stage also don't work...

Other commands in the dll work perfectly. I can pass strings and doubles in and out without troublem but not the BOOL type...

Do you guys have any idea what could be wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一梦等七年七年为一梦 2024-07-20 04:29:30

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

BOOL in C++ is actually an "int" so make sure you use System.Int32 and not System.Boolean.
Alternatively it might be using COM data types i.e. VARIANT_BOOL, in which case you need do need System.Boolean.
Have you tried running dependency viewer to confirm the function prototype?

两相知 2024-07-20 04:29:30

您是否尝试过指定 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 枚举的不同成员,并尝试其他人的建议。 不过,请尝试以上两种技巧,让我知道它们是否有助于排序!

Have you tried specifying the MarshalAs attribute, e.g.:-

[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);

Also, have you tried literally passing the sAxes string as a char array, e.g.:-

[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);

I've found that with interop you often need to experiment a fair bit to get it working, so try different combinations, check out the different members of the UnmanagedType enumeration and also play about with other people's suggestions too. However, please try the above two techniques and let me know whether they help sort it!

情丝乱 2024-07-20 04:29:30

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

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

This isn't going to answer your question directly but a sweet tool for getting common Interop Win32 calls easily is using Pinvoke.net The even have a Visual Studio plugin.

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

仅一夜美梦 2024-07-20 04:29:30

您的函数的文档< /a> 说:

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

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

CallConvention = CallingConvention.StdCall

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

CharSet = CharSet.Ansi

但即使没有这些,它也应该可以工作。 这很奇怪,因为你的代码看起来是正确的。

The docs for your function say:

The VC++ compiler needs an extern "C" modifier. The declaration must also specify that these functions are to be called like standard Win-API functions. That means the VC++ compiler needs to see a WINAPI or __stdcall modifier in the declaration.

The default calling convention for DllImport is WinApi. On Windows, that's StdCall. But on CE, that's Cdecl. You want to make sure that you use the right calling convention. You might want to tray adding:

CallConvention = CallingConvention.StdCall

Also, specify our string character set:

CharSet = CharSet.Ansi

But it should work even without these. It's quite odd as your code looks right.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文