Laden...

Probleme mit Interop C++ DLL Aufruf

Erstellt von wisher78 vor 9 Jahren Letzter Beitrag vor 9 Jahren 1.621 Views
wisher78 Themenstarter:in
101 Beiträge seit 2011
vor 9 Jahren
Probleme mit Interop C++ DLL Aufruf

Hallo,

ich versuche in meiner C# Applikation über Interop eine C++ DLL einzubinden.
Das Interface bietet beispielsweise folgenden Funktionsaufruf:


        void AT91Boot_Scan(ref byte pDevList);

Allerdings kommt es zu einem Fehler, wenn ich die Funktion aufrufe. Hierbei handelt es sich um eine AccessViolation mit der Fehler Meldung "Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben...". Dies liegt m.E.n. daran, dass die C++ DLL einen bereits allokierten Speicher möchte. Aber ich habe keinen direkten Plan, wie ich das lösen könnte.

Hat jemand eine Idee?

F
10.010 Beiträge seit 2004
vor 9 Jahren

Ist es möglich das du einfach eine falsche Interop Definition hast?
Wenn ich ref byte lese und dahinter dann pDevList dann denke ich du oder derjenige der die Interop aufrufe in C# umgesetzt hat, haben den Unterschied zwischen C# und C++ nicht bedacht.

Du gibst einen Pointer auf ein einzelnes Byte hinein, keinen Pointer auf ein ByteArray.

wisher78 Themenstarter:in
101 Beiträge seit 2011
vor 9 Jahren

Hallo FZelle,

bei der DLL handelt es sich um eine Third-Party Applikation. Ich habe keinen Einfluss auf die Interop Schnittstelle. Es gibt eine vermeintliche Lösung, auf folgender Seite beschrieben:
http://www.sparxeng.com/blog/software/c-pointer-array-for-atmel-sam-ba-dll-2-12

und hier der Code dazu


	//allocate block of raw bytes big enough for ten 100 byte buffers
	// and ten pointers. Since we are calling into a 32 bit dll, they
	// use 4 byte pointers so we need 1040 bytes (10*100 + 10*4)
	byte[] byteArray = new byte[1040];
	fixed (byte * pByteArray = byteArray)
	{
	     for (var i = 0; i < 10; i++ )
	     {
	          var memoryLocation = pByteArray + 40 + i*100;
	          var asInt = new IntPtr(memoryLocation).ToInt32();
	          var asBytes = BitConverter.GetBytes(asInt);
	          Buffer.BlockCopy(asBytes, 0, byteArray, i*4,4);
	     }
	     _sambadll.AT91Boot_Scan(ref byteArray[0]);
	}

Allerdings kommt es sporadisch bei Aufruf der Methode zum Programmabsturz. Ich denke, das ist eine unsaubere Lösung.

F
10.010 Beiträge seit 2004
vor 9 Jahren

Äh wie?

Einfach die Signatur ändern in etwas das sinn macht und gut.
Also aus

 void AT91Boot_Scan(ref byte pDevList);

ein

 void AT91Boot_Scan(ref byte[] pDevList);

oder

 void AT91Boot_Scan([In, Out, MarshalAs(UnmanagedType.LPArray, SizeConst = WelcheGrösse auch immer)] byte[] pDevList);

oder auch
https://social.msdn.microsoft.com/Forums/vstudio/en-US/87f5cf65-5722-4619-a2c5-1a1eba3dc835/how-to-marshal-a-c-array-of-strings-in-c-com-interop?forum=clr

Da muss man nicht irgendwie rumpinnen.

wisher78 Themenstarter:in
101 Beiträge seit 2011
vor 9 Jahren

Okay... Neuland.
Was heißt Signatur ändern? Die Schnittstelle der DLL steht doch in den Metadaten. Was kann ich da ändern?

wisher78 Themenstarter:in
101 Beiträge seit 2011
vor 9 Jahren

Okay, habe mich jetzt ein bisschen eingelesen. Ich kann mit dem Tool TlbImp eine neue Schnittstelle erzeugen in der ich die Methoden Signatur definieren kann, wie ich sie benötige. Ist das korrekt? Gibt zum Thema Tutorials? Marshalling scheint ein komplexes Thema zu sein.

W
872 Beiträge seit 2005
vor 9 Jahren

Edit:
Hast Du folgendes auf MSDN schon gesehen?

TlbImp würde klappen, wenn es eine COM Schnittstelle wäre. Scheint laut MSDN ja zuzutreffen.
Arbeitest Du mit try...catch?

wisher78 Themenstarter:in
101 Beiträge seit 2011
vor 9 Jahren

Ich arbeite mit try catch. Aber Wenn es zum sporadischen Fall des Absturzes kommt, nutzt auch das nichts.

Ja, habe diesen MSDN Eintrag gesehen.
Ich verstehe ihn wiefolgt:
(1)Mit tlbimp.exe erzeuge ich eine interop assembly. (2)Danach erzeuge ich eine MSIL für die DLL. Diese Schnittstelle kann ich dann entsprechend meiner Wünsche bearbeiten. (3)Mit dem Tool ilasm generiere ich aus der MSIL Datei wieder eine DLL mit der angepassten Schnittstelle.

Dies versuche ich gerade. Hänge an Schritt (3). Da sagt mit das tool ilasm: Error: No entry point declared for executable Could not create output file...

Mal sehen, vielleicht schaffe ich es heute noch.

wisher78 Themenstarter:in
101 Beiträge seit 2011
vor 9 Jahren

Schade, habe zwar alles wie im MSDN Link hinbekommen. Habe Signatur ändern können, und letzten Endes dann ein String-Array übergeben können, aber beim Aufruf der Methode kam es ebenfalls zum Programmabsturz.

Sehe allerdings gerade, dass die neu erzeugte DLL nur 5KB groß ist und die ursprüngliche DLL 48kb. Mache also wohl noch irgendetwas falsch.

W
872 Beiträge seit 2005
vor 9 Jahren

Ich würde mir mal das hier anschauen. Durch dynamic hat sich in dem Bereich einiges getan und ist einfacher geworden.