Zum Inhalt springen

VB Deklaration von Strukturen aus Header und C-dll-Funktion


NancyG

Empfohlene Beiträge

Hallo Leute,

ich habe ein Problem, mit der Deklaration von Strukturen in VB - und der Dek. einer C-dll.

Hier der Code aus der Header-Datei.

typedef struct tagDM_VARKEYA

{

    DWORD       dwKeyType;                                   

    DWORD       dwID;                                      

    char        szName[ MAX_DM_VAR_NAME + 1 ];                               

    LPVOID      lpvUserData;                                 

} DM_VARKEYA, FAR *LPDM_VARKEYA;

#if....

DM_VARKEY = DM_VARKEYA;

...

...

In VB steht dann dieses hier:
<StructLayout(LayoutKind.Sequential, Pack:=1)>

Public Structure DM_VARKEY

    Public dwKeyType As UInt32

    Public dwID As UInt32

    Public szName() As Char

    Public lpvUserData As IntPtr

End Structure
Und hier habe ich schon das erste Problem: Wie kann ich den szName auf 128 Byte setzen. Ein

Dim vKey as DM_VARKEY

Marshal.SizeOf(vKey)
sagt, dass die Struktur nur 12 Byte groß ist. 2 x DWORD (4 Byte) + 1 x IntPtr (4 Byte) = 12.. wo ist szName? Nun zur DLL. in der API_Doku steht dies hier:
BOOL DMGetValue (LPDM_VARKEY lpdmVarKey, DWORD dwItems, LPDM_VAR_UPDATE_STRUCT lpdmvus, LPCMN_ERROR lpdmError);

Unter C würde dies so aussehen.

CMN_ERROR err;

DM_VARKEY vKey;

DM_VAR_UPDATE_STRUCT update;

DWORD items = 1;


ZeroMemory(&vKey, sizeof(vKey));

ZeroMemory(&err, sizeof(err));


vKey.dwKeyType = DM_VARKEY_NAME; //DM_VARKEY_NAME = 2

strcpy(varKey.szName,"TESTVAR");

varKey.lpvUserData = NULL;


DMGetValue( &vKey, items, &update, &err ); //funktioniert super!

Wie muss die Funktion nun aber in VB deklariert werden? Ich habe es so gemacht, nur leider funktioniert das nicht.

Declare Ansi Function DM_GetValue Lib "dmclient.dll" Alias "DMGetValueA" _

        (ByVal lpdmVarKey As IntPtr, _

         ByRef dwItems As UInt32, _

         ByVal lpdmvus As IntPtr, _

         ByVal lpdmError As IntPtr) As Boolean

Ich hoffe, das Ihr mir da helfen könnt. Steh völlig auf dem Schlauch.

vG

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi NancyG,

ich habe ein Problem, mit der Deklaration von Strukturen in VB - und der Dek. einer C-dll.

Hier der Code aus der Header-Datei.

Das Zauberwort: Marshal. Wenn ich den Code so sehe - Siemens lässt grüßen!

Was du machen willst ist: managed mit unmanaged code. Beim .Net ist es so, dass sich Net um den Speicher kümmert, alloziert, freigibt usw... Diese Mechanismen gilt es für diesen Anwendungsfall auszuschalten.

Ein Stück davon hast du schon drin:

<StructLayout(LayoutKind.Sequential, Pack:=1)>
.
typedef struct tagDM_VARKEYA

{

    DWORD       dwKeyType;                                   

    DWORD       dwID;                                      

    char        szName[ MAX_DM_VAR_NAME + 1 ];                               

    LPVOID      lpvUserData;                                 

} DM_VARKEYA, FAR *LPDM_VARKEYA;

[/QUOTE]


Sollte so funktionieren:

[CODE]

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _

Public Class DM_VARKEY

    <MarshalAs(UnmanagedType.U4)> _

    Public dwKeyType As DM_VARKEY_TYPE

    <MarshalAs(UnmanagedType.U4)>

    Public dwID As UInt32

    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=(MAX_DM_VAR_NAME + 1))>

    Public szName As [String]

    Public lpvUserData As IntPtr

End Class

Es fehlt noch die Err_Struct :) :

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)>

Public Class CMN_ERROR

    <MarshalAs(UnmanagedType.U4)>

    Public dwError1 As UInt32

    Public dwError2 As UInt32

    Public dwError3 As UInt32

    Public dwError4 As UInt32

    Public dwError5 As UInt32


    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=512)>

    Public szErrorText As [String]


    Sub reset()

        dwError1 = 0

        dwError2 = 0

        dwError3 = 0

        dwError4 = 0

        dwError5 = 0

        szErrorText = ""

    End Sub


End Class

Mit [reset()] kannst du das Objekt schnell wieder leeren. Und hier die DLL:

<DllImport("dmclient.dll", EntryPoint:="DMGetValueA", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Winapi)> _

Private Shared Function DMGetValue(<[In]()> <MarshalAs(UnmanagedType.LPStruct)> ByVal lpdmVarKey As DM_VARKEY, _

                                   <[In]()> ByVal dwItems As UInt32, _

                                   <[In]()> ByVal lpdmvus As IntPtr, _

                                   <[In](), Out()> ByRef lpdmError As CMN_ERROR

                                  ) As Boolean

Ich würde dir aber die DMGetValueWait empfehlen. Bei dieser werden die Daten, sofern sie keine Internen Variablen sind, aus der SPS gelesen/synchronisiert. Die (WAIT) erwartet aber eine CallBack-Funktion, die du über DELEGATE realisieren kannst.

Du solltest darauf achten, dass du überall das gleiche CharSet benutzt. Ich empfehle CharSet.Ansi

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...