Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

pinvoke: Pointer to Pointer

4 views
Skip to first unread message

Curtis Newton

unread,
Feb 21, 2012, 6:18:06 AM2/21/12
to
Hallo,

ich habe hier in einer DLL folgendes:

typedef struct _DeviceKey
{
INT32 _serial;
void *_private;
} DeviceKey;

nebst dieser Funktion:

INT32 GetDeviceKeyListEntry(INT32 index, DeviceKey** device_key);

Mein Ansatz:

public class DeviceKey
{
Int32 _serial;
IntPtr _private;
};

[DllImport("My.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetDeviceKeyListEntry(Int32 index, out DeviceKey device_key);


Leider stürzt das Programm beim Aufruf ab. Wie mache ich es richtig?

C.

Jochen Kalmbach [MS MVP]

unread,
Feb 21, 2012, 6:30:55 AM2/21/12
to
Hallo Curtis!

>
> INT32 GetDeviceKeyListEntry(INT32 index, DeviceKey** device_key);
>
> Mein Ansatz:
>
> public class DeviceKey
> {
> Int32 _serial;
> IntPtr _private;
> };

Das muss struct sein und StructLayOut (Sequential)

>
> [DllImport("My.dll", CallingConvention = CallingConvention.Cdecl)]

Bist Du sicher, dass cdecl stimmt?
Auch bekommst Du ja ein *Array* zurück!

Ich habe die Beführchung, dass dies so nicht geht.....

Curtis Newton

unread,
Feb 21, 2012, 6:40:03 AM2/21/12
to
On 2012-02-21, Jochen Kalmbach [MS MVP] <nospa...@kalmbach-software.de> wrote:

> Das muss struct sein und StructLayOut (Sequential)

Okay, habe ich geändert. Ich rufe die Funktion auch jetzt so auf:

[DllImport("My.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetDeviceKeyListEntry(Int32 index, [MarshalAs(UnmanagedType.LPStruct)] out DeviceKey device_key);

>> [DllImport("My.dll", CallingConvention = CallingConvention.Cdecl)]
>
> Bist Du sicher, dass cdecl stimmt?

Ja, Funktion ist extra so deklariert.

> Auch bekommst Du ja ein *Array* zurück!

Ne, nicht ganz. Die Funktion wird so benutzt:

DeviceKey *key;
GetDeviceKeyListEntry(i, &key))

int i = key->....;


> Ich habe die Beführchung, dass dies so nicht geht.....

Schade.

C.

Curtis Newton

unread,
Feb 21, 2012, 7:19:04 AM2/21/12
to
On 2012-02-21, Curtis Newton <cne...@web.de> wrote:
>> Ich habe die Beführchung, dass dies so nicht geht.....
>
> Schade.

Geht doch. Funktion mit "ref IntPtr" deklarieren und aus dem IntPtr
mittels Marshal.PtrToStructure nachm struct konvertieren.

C.

Ulrich Eckhardt

unread,
Feb 21, 2012, 8:33:20 AM2/21/12
to
Am 21.02.2012 12:18, schrieb Curtis Newton:
> INT32 GetDeviceKeyListEntry(INT32 index, DeviceKey** device_key);
[...]
> [DllImport("My.dll", CallingConvention = CallingConvention.Cdecl)]
> public static extern int GetDeviceKeyListEntry(Int32 index, out DeviceKey device_key);

Bedeutet "out DeviceKey device_key" nicht dass der entsprechende
Parameter in C dann "DeviceKey* device_key" waere, also ohne doppelte
Indirektion? Das waere uebrigens auch mein Ansatz wenn ich kein Array
brauche.

Uli

Jochen Kalmbach [MS MVP]

unread,
Feb 21, 2012, 9:25:19 AM2/21/12
to
> Bedeutet "out DeviceKey device_key" nicht dass der entsprechende
> Parameter in C dann "DeviceKey* device_key" waere, also ohne doppelte
> Indirektion? Das waere uebrigens auch mein Ansatz wenn ich kein Array
> brauche.

Genau... deswegen hab ich da ja massive Bedenken....
Man müsste es als "IntPtr" dekalrieren und dann von Hand Marshallen...

Curtis Newton

unread,
Feb 22, 2012, 2:19:40 AM2/22/12
to
On 2012-02-21, Curtis Newton <cne...@web.de> wrote:

> Geht doch. Funktion mit "ref IntPtr" deklarieren und aus dem IntPtr
> mittels Marshal.PtrToStructure nachm struct konvertieren.

Jetzt habe ich ein anderes Problem:

Die C-Struktur:

#define MAX_STRING_LEN 300
typedef struct _DeviceKey
{
INT32 _serial;
char _manufacturer_str[MAX_STRING_LEN];
char _product_str[MAX_STRING_LEN];
char _device_str[MAX_STRING_LEN];
INT32 _busy;
} DeviceKey;

C#-Äquivalent:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DeviceKey
{
public Int32 _serial;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 300)]
public string _manufacturer_str;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 300)]
public string _product_str;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 300)]
public string _device_str;
public Int32 _busy;
};

Geht, aber nur in eine Richtung. Ich habe z.B. diese Funktion:

INT32 __cdecl OpenDevice(const DeviceKey *device_key, Device *device);

C#:

[DllImport("My.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int OpenDevice(out DeviceKey device_key, out IntPtr device);

Ändere ich den DeviceKey vor Aufruf der Funktion, kommt das nicht an.
Alles ist 0. Ändere ich den Key in der Funktion, kommt das aber raus,
heißt der Key ist geändert. Komisch,. C#-Beispiel:

DeviceKey key;
key._serial = 1234;

// debugge ich diese Funktion, ist key._serial 0 und nicht 1234
// innerhalb der Funktion wird key._serial auf 4321 gesetzt
GetDeviceKeyListEntry(0, out key);

/// key._serial ist jetzt 4321


C.

Curtis Newton

unread,
Feb 22, 2012, 3:00:25 AM2/22/12
to
On 2012-02-22, Curtis Newton <cne...@web.de> wrote:
> Geht, aber nur in eine Richtung. Ich habe z.B. diese Funktion:

> public static extern int OpenDevice(out DeviceKey device_key, out IntPtr device);
^^^
Da muss natürlich ref hin.

Sowas aber auch.


C.
0 new messages