1

I am trying to (for the past 10 hours.... grr) to make this thing work but so far whatever i tried - it refuses :)

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.

What is the problem?

I am trying to call a C DLL library method returning a 2d array of structs to c#.

But it seems i am doing something wrong regarding in how i read the data from c#.

I've developed a simple C console app and i am calling the DLL from there - all fine - no issues at all. Only the c# fails!

Here is the C implementation of the method:

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:

[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:

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

Unhandled exception: Access Violation

I guess i am not calculating the pointer properly but... i really tried a lot of different scenarios and nothing works.

HELP! :)

0

1 Answer 1

1

You are dereferencing p with p = (IntPtr)Marshal.PtrToStructure(p, typeof(IntPtr)); 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 :)
    }
Sign up to request clarification or add additional context in comments.

8 Comments

I seeee :) But it still goes bad :( Issue 1 is that (p += sSize) does not work - i am on 3.5 sdk - i guess that is the reason - so i've replaced it again with: p = new IntPtr(p.ToInt64() + sSize); The exception now is different: NullReferenceException - again on the 'ppstruct = ...' line. Before it is invoked 'p' has became zero.
Aaand i just solved it :))) I should be doing: p = new IntPtr(p.ToInt64() + IntPtr.Size); instead of: p = new IntPtr(p.ToInt64() + sSize); All perfect now! Thank you BIG!!!!!!
@MartinKovachev: Glad I could help :D p += IntPtr.Size; should work too then
It doesn't recognize the syntax. That's why i reworked it like this in the first place :) the + operation.
I know for sure it works in 4.0 - as i tested it - i guess it's a SDK addon.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.