简体   繁体   English

.NET Framework> = 4在64位上的本机ANSI C库

[英]Native ANSI C library from .NET Framework >= 4 on 64 Bit

I have a C# application that (P/)invokes an ANSI C library, provided by the manufacturer, to access an RFID-Reader over the network. 我有一个C#应用程序,该应用程序(P /)调用制造商提供的ANSI C库,以通过网络访问RFID阅读器。 This works absolutely fine with .NET Framework versions 2.0 up to 4.5 if I manually set the platform to x86. 如果我手动将平台设置为x86,则此功能在.NET Framework 2.0最高为4.5的版本中绝对可以正常工作。

With the platform set to 64 Bit on the other hand, it only works with .NET Framework versions <= 3.5. 另一方面,将平台设置为64位时,它仅适用于<= 3.5的.NET Framework版本。 The error code I get is defined as "InvalidHandle", where the handle is an int I'm given by the library identifying the reader. 我得到的错误代码定义为“ InvalidHandle”,其中句柄是由标识读者的库提供的int值。 I don't get what an impact the Framework Version could have on a native library, especially if only so on a 64 Bit platform. 我不了解Framework版本对本机库可能产生什么影响,尤其是在64位平台上时。

What I've observed, although I'm not sure if it is relevant at all: - In the case of failure, the handle is 10 digits long, sometimes positive, sometimes negative - In the case of success, the handle is 9 digits long, always positive 我观察到的内容,尽管我不确定是否完全相关:-在失败的情况下,句柄为10位数字,有时为正,有时为负-在成功的情况下,句柄为9位数字长期,总是积极的

Based on this observation I've tried other data types (int, uint, long, ulong) without success (and with the same behaviour). 基于此观察,我尝试了其他数据类型(int,uint,long,ulong),但均未成功(并且行为相同)。

The "setup" of the component consists of multiple steps (method calls), which are: 1. Init (where I get the handle from) 2. SetChannel (takes a byte as a parameter) 3. SetAddress (takes a connection string containing an IP and a Port as parameter) 4. Open() Note: All those methods take the handle as an int out-parameter. 组件的“设置”包含多个步骤(方法调用),这些步骤是:1. Init(从中获取句柄)2. SetChannel(采用字节作为参数)3. SetAddress(采用包含以下内容的连接字符串) IP和端口作为参数)。4. Open()注意:所有这些方法都将句柄作为int输出参数。 Because the method SetAddress fails, when Init and SetChannel also take the handle as a parameter but don't, I suspect it might have something to do with the string, although I haven't found any evidence to support this theory. 因为方法SetAddress失败,所以当Init和SetChannel也将句柄作为参数但没有这样做时,我怀疑它可能与字符串有关,尽管我没有找到任何证据来支持该理论。

Unfortunately the documentation is close to non-existent. 不幸的是,该文档几乎不存在。

So any ideas are greatly appreciated. 因此,任何想法都将受到赞赏。 If you need more information, I'd be glad to provide it. 如果您需要更多信息,我们很乐意提供。

Regards, 问候,

Pascal 帕斯卡尔

[DllImport("/x64/BLUEBOXLib.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
static extern int BLUEBOX_Init(out int Handle);

[DllImport("/x64/BLUEBOXLib.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
static extern int BLUEBOX_SetAddress(ref int Handle, byte Address);

[DllImport("/x64/BLUEBOXLib.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
static extern int BLUEBOX_SetChannel(ref int Handle, String Channel, String Settings);

Excerpt from the BLUEBOXLib.h file: 摘自BLUEBOXLib.h文件:

BLUEBOXLib_API BLUEBOX_ErrorCodes __stdcall BLUEBOX_Init (BLUEBOX_Handle *Handle);

BLUEBOXLib_API BLUEBOX_ErrorCodes __stdcall BLUEBOX_SetChannel (BLUEBOX_Handle *Handle, char *Channel, char *Settings);

BLUEBOXLib_API BLUEBOX_ErrorCodes __stdcall BLUEBOX_SetAddress (BLUEBOX_Handle *Handle, unsigned char Address);

typedef int BLUEBOX_Handle;
    typedef int BLUEBOX_Handle;

That is a problem, one you cannot fix because it doesn't appear in your code. 这是一个问题,您无法解决,因为它没有出现在您的代码中。 There are multiple ways to implement a handle but they basically fall into two distinct categories. 有多种实现句柄的方法,但它们基本上分为两个不同的类别。 Either it a simple index into an internal array or it is a plain pointer. 它可以是进入内部数组的简单索引,也可以是普通指针。 When you see "10 digits long, sometimes positive, sometimes negative" then it is 99% odds for a pointer. 当您看到“ 10位长,有时为正,有时为负”时,则指针的几率是99%。

That pointer takes 8 bytes in 64-bit mode, it cannot fit in an int . 该指针在64位模式下占用8个字节,不能容纳在int中 And yes, this sometimes still works, it depends on the operating system and the simplicity of the test program. 是的,这有时仍然可行,这取决于操作系统和测试程序的简单性。 On the x64 version of Vista or Win7, a 64-bit pointer can still fit in a 32-bit value by accident, allocations often happen in the lower 2 GB address range. 在Vista或Win7的x64版本上,偶然仍然可以将64位指针容纳在32位值中,分配通常发生在较低的2 GB地址范围内。 You'll have zero odds for success on Win8, also a hint why it might seem to work on .NET 3.5. 您将在Win8上获得零成功的几率,也暗示了为什么它似乎可以在.NET 3.5上运行。 And yes, negative values won't work because they'll sign-extend when the C code casts the handle to the real pointer type, producing a garbage pointer value. 是的,负值将不起作用,因为当C代码将句柄强制转换为实数指针类型时,它们会符号扩展,从而产生垃圾指针值。

You cannot fix this bug, it has to be fixed by the vendor. 您无法修复此错误,必须由供应商修复。 They have to change the typedef to void* , now you can use IntPtr on your end. 他们必须将typedef更改为void* ,现在您可以在端使用IntPtr了。 Give them a call. 给他们打个电话。 If they are unresponsive, then consider running this code in a separate 32-bit helper process that you interop with. 如果它们没有响应,请考虑在您与之交互的单独的32位帮助器进程中运行此代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM