通过引用传递的参数使用 P/Invoke 返回垃圾 [英] Parameters passed by reference come back garbage using P/Invoke

查看:20
本文介绍了通过引用传递的参数使用 P/Invoke 返回垃圾的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Linux 上使用 Mono/C#,并且有以下 C# 代码:

[DllImport("libaiousb")]extern static ResultCode QueryDeviceInfo(uint deviceIndex,ref uint PID、ref uint nameSize、StringBuilder 名称、ref uint DIOBytes,ref uint 计数器);

我调用了一个Linux共享库调用,定义如下:

unsigned long QueryDeviceInfo(无符号长设备索引, 无符号长 *pPID, 无符号长 *pNameSize, 字符 *pName, 无符号长 *pDIOBytes, 无符号长 *pCounters)

在调用 Linux 函数之前,我已将参数设置为已知值.我还在 Linux 函数的开头放了一个 printf,所有参数都按预期打印值.所以参数似乎从C#传递到Linux ok.返回值也不错.

但是,通过引用传递的所有其他参数都会返回垃圾.

我修改了 Linux 函数,因此它只是修改了值并返回.这是代码:

unsigned long QueryDeviceInfo(无符号长设备索引, 无符号长 *pPID, 无符号长 *pNameSize, 字符 *pName, 无符号长 *pDIOBytes, 无符号长 *pCounters) {printf ("PID = %d, DIOBYtes = %d, Counters = %d, Name= %s", *pPID, *pDIOBytes, *pCounters, pName);*pPID = 9;*pDIOBytes = 8;*pCounters = 7;*pNameSize = 6;返回 AIOUSB_SUCCESS;

所有的 ref 参数仍然作为垃圾返回.

有什么想法吗?

解决方案

libaiousb.c

unsigned long QueryDeviceInfo(无符号长设备索引, 无符号长 *pPID, 无符号长 *pNameSize, 字符 *pName, 无符号长 *pDIOBytes, 无符号长 *pCounters){*pPID = 9;*pDIOBytes = 8;*pCounters = 7;*pNameSize = 6;返回0;}

libaiousb.so

<上一页>gcc -shared -o libaiousb.so libaiousb.c

Test.cs

使用系统;使用 System.Runtime.InteropServices;使用 System.Text;类测试{[DllImport("libaiousb")]静态外部 uint QueryDeviceInfo(uint deviceIndex,ref uint pid,ref uint nameSize,StringBuilder 名称,ref uint dioBytes,ref uint 计数器);静态无效主要(){uint deviceIndex = 100;uint pid = 101;单位名称大小 = 102;StringBuilder 名称 = new StringBuilder("Hello World");uint dioBytes = 103;uint 计数器 = 104;uint 结果 = QueryDeviceInfo(deviceIndex,参考 pid,参考名称大小,名称,参考 dioBytes,参考计数器);Console.WriteLine(deviceIndex);Console.WriteLine(pid);Console.WriteLine(nameSize);Console.WriteLine(dioBytes);Console.WriteLine(计数器);Console.WriteLine(结果);}}

Test.exe

<上一页>gmcs 测试.cs

运行:

<上一页>$ 单声道测试.exe10096870

I am using Mono/C# on Linux and have the following C# code:

[DllImport("libaiousb")]
extern static ResultCode QueryDeviceInfo(uint deviceIndex, 
    ref uint PID, ref uint nameSize, StringBuilder name, 
    ref uint DIOBytes, ref uint counters);

And I call a Linux shared library call defined as follows:

unsigned long QueryDeviceInfo(
      unsigned long DeviceIndex
    , unsigned long *pPID
    , unsigned long *pNameSize
    , char *pName
    , unsigned long *pDIOBytes
    , unsigned long *pCounters
    )

I have set the parameters to known values before calling the Linux function. I've also put a printf at the beginning of the Linux function and all the parameters are printing values as expected. So the parameters seem to be passed from C# to Linux ok. The return value is also good.

However, all the other parameters that are passed by reference come back garbage.

I modified the Linux function so it simply modifies the values and returns. Here's that code:

unsigned long QueryDeviceInfo(
    unsigned long DeviceIndex
    , unsigned long *pPID
    , unsigned long *pNameSize
    , char *pName
    , unsigned long *pDIOBytes
    , unsigned long *pCounters
) {
printf ("PID = %d, DIOBYtes = %d, Counters = %d, Name= %s", *pPID, *pDIOBytes, *pCounters, pName);
*pPID = 9;
*pDIOBytes = 8;
*pCounters = 7;
*pNameSize = 6;
return AIOUSB_SUCCESS;

All the ref parameters still come back as garbage.

Any ideas?

解决方案

libaiousb.c

unsigned long QueryDeviceInfo(
     unsigned long deviceIndex
   , unsigned long *pPID
   , unsigned long *pNameSize
   , char *pName
   , unsigned long *pDIOBytes
   , unsigned long *pCounters
   )
{
   *pPID = 9;
   *pDIOBytes = 8;
   *pCounters = 7;
   *pNameSize = 6;
   return 0;
}

libaiousb.so

gcc -shared -o libaiousb.so libaiousb.c

Test.cs

using System;
using System.Runtime.InteropServices;
using System.Text;

class Test
{
    [DllImport("libaiousb")]
    static extern uint QueryDeviceInfo(uint deviceIndex,
        ref uint pid, ref uint nameSize, StringBuilder name,
        ref uint dioBytes, ref uint counters);

    static void Main()
    {
        uint deviceIndex = 100;
        uint pid = 101;
        uint nameSize = 102;
        StringBuilder name = new StringBuilder("Hello World");
        uint dioBytes = 103;
        uint counters = 104;

        uint result = QueryDeviceInfo(deviceIndex,
            ref pid, ref nameSize, name,
            ref dioBytes, ref counters);

        Console.WriteLine(deviceIndex);
        Console.WriteLine(pid);
        Console.WriteLine(nameSize);
        Console.WriteLine(dioBytes);
        Console.WriteLine(counters);
        Console.WriteLine(result);
    }
}

Test.exe

gmcs Test.cs

Run:

$ mono Test.exe
100
9
6
8
7
0

这篇关于通过引用传递的参数使用 P/Invoke 返回垃圾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆