通过.NET中的指针从本机方法返回数据

本文关键字:本机 方法 返回 数据 指针 NET 通过 | 更新日期: 2023-09-27 18:25:59

我调用的函数是一个模糊的API的一部分,该API无法PInvoked,因为库的唯一入口点是指向其中函数的指针结构。话虽如此,我有C++的结构和实现示例代码。

tl;dr我不想看这个功能。

以下是C++中的实现情况

// Definition
extern  "C"  typedef short  (* GETBIT)(short,char*);
// Base function for using API
void anApi::GetData(short index, void* pData)
{
    switch(internal logic...)
    {
        case bitData:
            get_bit(index, (char *)(pData));
        case (other data types)...
    }
}
// Higher level API implementation
UCHAR u1Val = 0;
GetData( 1234, &u1Val );
if( u1Val == 1 )
{
    doSomthing();
}

大概我应该返回0或1(即使实际的数据类型是这样的)。我应该提到API有错误检查,为了简单起见,我省略了它,并且我的代码不会导致任何错误。还有一个初始化函数成功了,所以我知道我调用这些函数是正确的。

以下是我如何在C#中实现相同的功能

// Definition
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate short get_bit_delegate(short index, out byte data);
get_bit_delegate get_bit; 
// Base function
public string GetDataBit(short index)
{
    string ReturnData = "test";       
    // Using .NET type of Byte instead of char...
    byte myByte = 0;              
    lRetCode = get_bit(index, out myByte);
    // get a good look at what we returned
    ReturnData = Convert.ToString(myByte, 2).PadLeft(8, '0');
    return ReturnData;
    // error checking snipped for brevity 
}
// Implementation
 textBox1.Text = GetDataBit(1234);

我尝试过不同的数据类型,包括IntPtr和Marshaling,但我一直得到相同的结果:

11111111(ï)

他们在示例代码中使用结果的方式,我认为返回值应该是"1"或"0"。事实上,在我的测试用例中,我希望看到0。

0-chr(48)-00110000
1-chr(49)-00110001

通过.NET中的指针从本机方法返回数据

这一切都可以归结为您试图调用的函数的契约,您没有告诉我们太多:它应该返回一个字符、一个字节、一个位、一个布尔值吗?

如果您正在调用的函数应该返回一个字符,那么您应该期望chr(48)chr(49)。但很明显,你没有收到。不要注意char在内部使用的事实:char在旧式C代码中代替了字节、位和布尔值。因此,你必须遵循某种规范,而不是试图对其他人的代码内部进行字面解读。

在C族语言中,if()语句检查某个东西是零(FALSE)还是非零(TRUE)。因此,当某个值被假定为TRUE时,它不必等于1,它可以是任何非零值。实际上,-1并不罕见。

所有1s的位模式都是非零值,因此如果将其检查为布尔值,则它对应于TRUE。(在2的补码中,所有1s的位模式实际上是-1。)因此,很可能您正在调用的函数应该返回布尔值,而实际上您正在接收TRUE

(当然,鉴于此,像if( u1Val == 1 )这样的代码有点奇怪,它应该是if( u1Val != 0 ),所以可能有什么可疑之处。)