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?
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.
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.
Ä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);
Da muss man nicht irgendwie rumpinnen.
Okay... Neuland.
Was heißt Signatur ändern? Die Schnittstelle der DLL steht doch in den Metadaten. Was kann ich da ändern?
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.
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.
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.