简体   繁体   English

将结构的C数组编组为C#

[英]Marshaling C array of structs into c#

I am trying to (for the past 10 hours.... grr) to make this thing work but so far whatever i tried - it refuses :) 我正在尝试(在过去的10个小时内.... grr)使此功能正常工作,但到目前为止,无论我尝试了什么-它都拒绝:)

Basically i am doing a favor for someone - my strength is not windows / .NET coding for sure and i am trying to patch in some code from something i already have around. 基本上,我正在为某人提供帮助-我的实力肯定不是Windows / .NET编码,并且我正尝试从已有的东西中修补一些代码。

What is the problem? 问题是什么?

I am trying to call a C DLL library method returning a 2d array of structs to c#. 我试图调用C DLL库方法,将二维结构数组返回给c#。

But it seems i am doing something wrong regarding in how i read the data from c#. 但是似乎我在从c#中读取数据方面做错了。

I've developed a simple C console app and i am calling the DLL from there - all fine - no issues at all. 我已经开发了一个简单的C控制台应用程序,并且从那里调用DLL-很好-完全没有问题。 Only the c# fails! 只有C#失败!

Here is the C implementation of the method: 这是该方法的C实现:

int get_available_devices(idevice_info_t **devices, uint32_t *count) {
char **dev_list = NULL;
char *dev_name = NULL;
int i, total_devices;

if (idevice_get_device_list(&dev_list, &total_devices) < 0) {
    fprintf(stderr, "ERROR: Unable to retrieve device list!\n");
    return -1;
}

idevice_info_t *tmpArr = (idevice_info_t*)calloc(total_devices, sizeof(idevice_info));

int ii = 0;
int res_name = 0;

idevice_info_t dtmp = NULL;

for (i = 0; i <= total_devices - 1; i++) {
    res_name = idevice_get_device_name(dev_list[i], &dev_name);
    dev_name = (res_name == 0 ? dev_name : "");

    printf("%s: %s\n", dev_name, dev_list[i]);

    dtmp = (idevice_info_t)malloc(sizeof(struct idevice_info));
    strncpy_s(dtmp->udid, sizeof dtmp->udid - 1, dev_list[i], sizeof dtmp->udid - 1);
    strncpy_s(dtmp->name, sizeof dtmp->name - 1, dev_name, sizeof dtmp->name - 1);
    tmpArr[i] = dtmp;
}
idevice_device_list_free(dev_list);

*devices = tmpArr;
*count = total_devices;

return 0;}

Here is what i am doing in c# side: 这是我在C#方面正在做的事情:

[DllImport(LIBNAME, CallingConvention = CallingConvention.Cdecl)]
    static public extern short get_available_devices(out IntPtr devices, out uint count);

public static Dictionary<string, string> getAvailableDevices()
    {
        IntPtr p = IntPtr.Zero;
        Dictionary<string, string> ret = null;

        uint totalDevices = 0;

        int res = External.get_available_devices(out p, out totalDevices);

        if (res != 0 || totalDevices < 1)
        {
            return null;
        }

        ret = new Dictionary<string, string>();

        External.idevice_info ppStruct;
        int sSize = Marshal.SizeOf(typeof(External.idevice_info));

        for (int i = 0; i <= totalDevices - 1; i++)
        {
            p = (IntPtr)Marshal.PtrToStructure(p, typeof(IntPtr));
            ppStruct = (External.idevice_info)Marshal.PtrToStructure(p, typeof(External.idevice_info));

            ret.Add(ppStruct.udid, ppStruct.name);

            p = new IntPtr(p.ToInt64() + sSize);
        }

        return ret;
    }

What is the actual problem? 实际问题是什么?

As soon as i reach the second iteration of the for cycle() i get an access violation: 一旦到达for cycle()的第二次迭代,我就会遇到访问冲突:

An unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll

未处理的异常:访问冲突

I guess i am not calculating the pointer properly but... i really tried a lot of different scenarios and nothing works. 我想我没有正确计算指针,但是...我确实尝试了很多不同的情况,但没有任何效果。

HELP! 救命! :) :)

You are dereferencing p with p = (IntPtr)Marshal.PtrToStructure(p, typeof(IntPtr)); 您使用p = (IntPtr)Marshal.PtrToStructure(p, typeof(IntPtr));取消引用p and then at the end when trying to increment, all hell breaks loose. 然后在尝试增加时最后,所有地狱都松散了。

Use a fresh local so that the original pointer is not continuously dereferenced. 使用新鲜的本地,以便不会连续取消对原始指针的引用。

Eg: 例如:

    for (int i = 0; i <= totalDevices - 1; i++)
    {
        IntPtr pp = (IntPtr)Marshal.PtrToStructure(p, typeof(IntPtr));
        ppStruct = (External.idevice_info)Marshal.PtrToStructure(pp, 
                      typeof(External.idevice_info));

        ret.Add(ppStruct.udid, ppStruct.name);

        p += sSize; // easier, does the same :)
    }

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

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