Laden...

Wieder mal ein DLL Import

Erstellt von Duncan vor 18 Jahren Letzter Beitrag vor 18 Jahren 1.687 Views
D
Duncan Themenstarter:in
24 Beiträge seit 2006
vor 18 Jahren
Wieder mal ein DLL Import

Hi!

Hoffe hier kennt sich jemand mit Marshalling und/oder IntPtr aus.
Ich versuche leider vergeblich seit einigen Tagen die Funktionen einer DLL
in ein kleines Testprogramm einzubinden, funzt aber net richtig.

Hier mal die Definition der Funktion in der DLL.

 __declspec(dllexport) BYTE __stdcall SOFCommand(
TPorts FPort,
BYTE FAccessCode,
char FCommand,
char FCommandMode,
BYTE *FParameters,
int PLen,
unsigned char *RXData,
int *RXLen);

TPorts ist ein enum, also net davon verwirren lassen.Meine bisherigen Versuche haben mich zu dieser Definition geführt:


[DllImport("SOF.dll", EntryPoint = "#6", CharSet=CharSet.Auto)]
extern static byte SOFCommand(
TPorts FPort,
byte FAccessCode,
char FCommand,
char FCommandMode,
IntPtr FParameters,
int PLen,
IntPtr RXData,
IntPtr RXLen);

So das Problem ist hier nun folgendes. Für RXLen krieg ich nur 0 und ich befürchte das die Daten
die ich für RXData krieg auch net korrekt sind.

Ich weiß leider net wo der Fehler liegt, könnte auch sein das ich das Ganze irgendwie falsch aufrufe.

Bin kurz vorm Verzweifeln und bin für jede Hilfe dankbar.

Lg
Duncan

N
177 Beiträge seit 2006
vor 18 Jahren

Mal andersrum gefragt: Warum nimmst du nicht C++/CLI?

D
Duncan Themenstarter:in
24 Beiträge seit 2006
vor 18 Jahren

Sorry versteh die Frage net ganz.

Naja vielleicht beantwortet das trotzdem deine Frage.

Die Applikation die in weiterer Folge auf diese und weitere DLL-Funktionen
zugreifen soll ist in C# geschrieben.

Diese DLL ist vom Hersteller so vorgegeben und ich will das ganze
Protokoll net selbst coden.(Vorerst net)

N
177 Beiträge seit 2006
vor 18 Jahren

Was war zuerst da, die DLL oder die C#-Applikation? Wenn man schon wusste, dass man die C-DLL einsetzen wird, dann war die Entscheidung für C# vermutlich bereits falsch. C#-Wrapper zu schreiben ist nervig und mühsam. Entweder man schaut sich bekannte C#-Wrapper zum Lernen an und macht sich dann die Mühe einen Eigenen zu schreiben oder man benutzt C++/CLI.

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo nop,

ich kann dir nicht zustimmen. Es ist ganz normal, aus einer C#-Anwendung heraus bestehende Funktionen aus anderen Sprachen zu nutzen.

Außerdem muss man mit DllImport normalerweise keine Wrapper schreiben.

herbivore

N
177 Beiträge seit 2006
vor 18 Jahren

Ich benutze den bereits geschriebenen C#-OpenGL-Wrapper. Sowas zu schreiben macht sicherlich keinen Spass, besonders wenn man fremddefinierte Strukturen benutzt und Daten zurückbekommt (wie in Duncans Beispiel). Wenn es jetzt unbedingt C# mit C-Dll sein soll, warum macht man sich dann nicht die Arbeit und schaut in die Doku oder studiert andere bekannte Wrapper? Duncan scheint ja nun kein Anfänger zu sein.

D
Duncan Themenstarter:in
24 Beiträge seit 2006
vor 18 Jahren

Danke für eure Beiträge.
Ich wollte hier keine Grundsatzdiskussion lostreten .. 🙂

Nach eingehenden Studium des Forums, msdn und allen mir noch zu Verfügung stehenden Quellen, sollte das ja "ganz einfach" mittels Marshal gehen.

Dies ist aber leider nicht der Fall.

Was ich nun bräuchte wär einfach ein Code Snippet für den gängigen Fall.


void GetSomethingImportant(unsigned char *ImpData, int *ImpDataLength);

Denn wenn man alles andere abstrahiert ist genau das das Problem.

Ich hab bisher alles probiert was sinnvoll erschien(ref, out, IntPtr).

Irgendwas scheine ich falsch zu machen, kriege keine sinnvollen Daten aus der verd***ten DLL raus.


[DLLImport("ThisLittledamned.dll", EntryPoint = "#2", Charset=Charset.Ansi)]
extern static void GetSomethingImportant(
IntPtr prxData, 
ref int len);

byte[] rxData = new byte[150];
IntPtr prxData  = Marshal.AllocHGlobal(rxData.Length * sizeof(byte));
int len = 0;
Marshal.Copy(rxData, 0, prxData, rxData.Length);
GetSomethingImportant(prxData, ref len);
Marshal.Copy( prxData,rxData,0, len);

len ist immer null.
Hab auch schon versucht, rxData.Length beim 2. Copy, krieg zwar was raus, scheint aber net sinnvoll zu sein.

Es ist wirklich zum Verzweifeln..

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Duncan,

also ich würde meinen, auf

void GetSomethingImportant(unsigned char *ImpData, int *ImpDataLength);

passt

... (String ImpData, ref int ImpDataLength)

wenn ImpData ein null-terminierter String ist.

herbivore

D
Duncan Themenstarter:in
24 Beiträge seit 2006
vor 18 Jahren

Glaube nicht das es ein null-terminierter String ist, da ja die Länge angeben wird.
Wäre ja net notwendig, in diesem Fall. (Es sei denn die Länge sei zur Validierung notwenig, aber das ist nicht wahrscheinlich)

Ich geh davon aus das in diesem unsigned char* , irgendwelcher Schrott drinnen ist.

Im vom Hersteller mitgelieferten Testprogramm wird diese Variable so weiter verwendet:

 

      if ((ImpData[i]<0x20) || ImpData[i]>0x80)
        RStr=RStr+" ";
      else
        RStr=RStr+(AnsiString)(char)ImpData[i];
      }

Was an dem Ganzen so seltsam ist, ist das ich für die Länge nie was zurück bekomme.

D
Duncan Themenstarter:in
24 Beiträge seit 2006
vor 18 Jahren

Danke für die Hilfe.

Bin selbst dahintergekommen. War ein seltsamer Konfigurationsfehler.

Naja RS232 über nen USB - Adapter ansprechen.... dann kann sowas anscheinend vorkommen.

Lg Duncan