Laden...

DLLImport: Wie void* als Parametertyp umsetzen?

Erstellt von snowy vor 14 Jahren Letzter Beitrag vor 14 Jahren 7.062 Views
S
snowy Themenstarter:in
143 Beiträge seit 2009
vor 14 Jahren
DLLImport: Wie void* als Parametertyp umsetzen?

Hallo,

Ich möchte eine DLL einbinden, in der Hilfe ist das Einbinden einer Funktion davon wie folgt beschrieben:


[C#]

unsafe public static extern uint CAN_GetHwParam(

    byte hHw,

    ushort Param, 

    void* Buff, 

    ushort BuffLen

);  

Hier wird ja ein Zeiger verwendet im C# Code..? Hat das was mit dem unsafe zu tun.Also C/C++ Code?

In meiner Zugriffsklasse auf die DLL habe ich folgendes definiert:


[DllImport("CANAPI2.dll", EntryPoint = "CAN_GetHwParam")]    
            unsafe public static extern uint GetHwParam(byte hHw, ushort Param, ref char[] Buff, ushort BuffLen);

Wenn ich diese funktion jetzt verwenden will:


ret = CanApi2.GetHwParam(0, CanApi2.PARAM_NAME, ref szBuff, Convert.ToUInt16(szBuff.Length));

Kommt die Exception:

System.ExecutionEngineException

Was habe ich falsch gemacht?

Mein zweites Problem ist das ich noch eine andere TP.DLL verwende. Dies hatte vor dem einbinden der CANAPI2.DLL funktioniert. Jetzt findet er die TP.DLL auf einmal nicht mehr..

Woran kann das jetzt liegen..?

Danke!

J
641 Beiträge seit 2007
vor 14 Jahren
Unsafe???

Unsicheren code zulassen in den Projekt eigenschaften hast du angekreuzt???

cSharp Projekte : https://github.com/jogibear9988

S
snowy Themenstarter:in
143 Beiträge seit 2009
vor 14 Jahren

Ja das habe ich gemacht, weil vorher eine dementsprechende Fehlermeldung kam..

S
snowy Themenstarter:in
143 Beiträge seit 2009
vor 14 Jahren

Jetzt habe ich mal die Funktion wie in der Hilfe dokumentiert deklariert:


 [DllImport("CANAPI2.dll", EntryPoint = "CAN_GetHwParam")]
            unsafe public static extern uint GetHwParam(byte hHw,ushort Param,void* Buff,ushort BuffLen);  

kann ich hier also Zeiger verwenden, weil das unsafe Code ist?

Aber wie rufe ich die Funktion jetzt auf?


ret = CanApi2.GetHwParam(0, 0, &szBuff, Convert.ToUInt16(szBuff.Length));

Fehler 1 Zeiger und Puffer fester Größe können nur in einem unsicheren Kontext verwendet werden.

Fehler 2 Es ist nicht möglich, einen Zeiger für den verwalteten Typ ("char[]") zu deklarieren oder dessen Adresse oder Größe abzurufen.

F
10.010 Beiträge seit 2004
vor 14 Jahren
  1. Du benötigst sehr selten unsave für apiaufrufe.

  2. Du hast auch den buffer vorher mit new angelegt?

S
snowy Themenstarter:in
143 Beiträge seit 2009
vor 14 Jahren

unsafe
                    {
                        char[] szBuff;
                        szBuff = new char[CanApi2.MAX_DRIVERNAMLEN];
                    
                        ret = CanApi2.GetHwParam(0, 0, &szBuff, Convert.ToUInt16(szBuff.Length));
                    }

So habe ich jetzt nochmal den Aufruf probiert.Jetzt kommt nur noch eine Fehlermeldungbei "&szBuff":

Fehler 1 Es ist nicht möglich, einen Zeiger für den verwalteten Typ ("char[]") zu deklarieren oder dessen Adresse oder Größe abzurufen.

D
95 Beiträge seit 2006
vor 14 Jahren

Es sollte allerdings möglich seinen, einen Zeiger auf das erste Element zu übergeben:

&(szBuff[0])

Kann es gerade nicht testen, sollte aber so funktionieren.

Dust Signs

Die Nummer, die Sie gewählt haben, ist imaginär. Bitte drehen Sie Ihr Telefon um 90° und versuchen Sie es erneut.

S
248 Beiträge seit 2008
vor 14 Jahren

Hallo,

Wenn ich mir die Funktion so ansehe, gehe ich einmal davon aus, dass Parameter "Buff" ein Buffer ist in den etwas geschrieben wird, welcher die Länge "BuffLen" hat.
Das ganze funktioniert auch ganz ohne unsafe code:


[DllImport("CANAPI2.dll", EntryPoint = "CAN_GetHwParam")]
public static extern uint GetHwParam(byte hHw, ushort Param, byte[] Buff, ushort BuffLen);

...
const int buffLength = 1024;
byte[] buffer = new buffer[buffLength];
uint result = GetHwParam(0, 0, buffer, buffLength);

...


Ob die Funktion bytes, shorts, ect erwartet musst du der API entnehmen.

Spooky

S
snowy Themenstarter:in
143 Beiträge seit 2009
vor 14 Jahren

@Dust:


unsafe
                    {
                        char[] szBuff;
                        szBuff = new char[CanApi2.MAX_DRIVERNAMLEN];

                        ret = CanApi2.GetHwParam(0, 0, &(szBuff[0]), Convert.ToUInt16(szBuff.Length));
                    }

liefert:


Fehler	1	Sie können nur die Adresse eines unfixed-Ausdrucks innerhalb eines fixed-Anweisungsinitialisierers abrufen.	

S
snowy Themenstarter:in
143 Beiträge seit 2009
vor 14 Jahren

@Spook:


uint ret=0;
const int buffLength = 1024;
                    byte[] buffer;
                    buffer= new byte[buffLength];
                    ret = CanApi2.GetHwParam(0, 0, buffer, buffLength);

So klappt der Aufruf jetzt (auch ohne unsafe wie in deinem Beitrag)!

Was ist jetzt aber mit meinem zweiten Problem..Woran könnte das liegen das die andere DLL aufeinmal nicht mehr gefunden wird. Hatte Die auch neu erstellt und nochmal reinkopiert in den Projektordner..

1.361 Beiträge seit 2007
vor 14 Jahren

DllImport("CANAPI2.dll", EntryPoint = "CAN_GetHwParam")]
public static extern uint GetHwParam(byte hHw, ushort wParam, [Out] byte[] pBuff, ushort wBuffLen);

const int buffLength = 1024;
byte[] buffer = new buffer[buffLength];
uint result = CanApi2.GetHwParam(0, CanApi2.PARAM_NAME, buffer, buffLength);

Das [Out] ist wichtig, sonst "siehst" du das Ergebnis nicht.
Und es sollte schon byte[] sein und nicht char[]. Da können ja schließlich auch andere Sachen als Strings zurückkommen. Zudem ist ein char=2bytes groß.

beste Grüße
zommi

S
248 Beiträge seit 2008
vor 14 Jahren

Hallo,

das out ist nicht nötig, da .NET den Zeiger auf das erste Array-Element übergibt und die Daten direkt in dieses geschrieben werden (genau das, was vorher manuell mit unsafe erreicht werden sollte).

Spooky

1.361 Beiträge seit 2007
vor 14 Jahren

das out ist nicht nötig

Stimmt, mein Fehler.

Ich würds vielleicht trotzdem hinschreiben. Zeigt's nochmal auf, dass das was zurückkommt.

beste Grüße
zommi

S
snowy Themenstarter:in
143 Beiträge seit 2009
vor 14 Jahren

mit dem out kommt wieder die EngineException.

S
snowy Themenstarter:in
143 Beiträge seit 2009
vor 14 Jahren

Hat jemand eine Idee warum die andere DLL jetzt nicht mehr gefunden wird (DLLNotFoundException)?