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

时间:2015-12-07 22:38:29

标签: c# c++ api type-conversion

我正在调用的函数是一个不能被PInvoked的模糊API的一部分,因为库的唯一入口点是指向其中函数的指针结构。话虽这么说,我有结构和C ++实现示例代码。

  

tl; dr我不是PInvoking这个函数。

以下是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

1 个答案:

答案 0 :(得分:0)

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

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

在C语言系列中,if()语句检查某些内容是零(FALSE)还是非零(TRUE)。因此,当某些内容被评估为TRUE时,它不必等于1,它可以是任何非零值。实际上,-1并不罕见。

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

(当然,鉴于此,像if( u1Val == 1 )这样的代码有点奇怪,应该是if( u1Val != 0 ),所以可能会有一些可疑的东西。)