2009-03-29 15 views
1

Dies ist mein 3. Thread bezüglich eines Blowfish-Problems in C#. Obwohl ich Blowfish nicht in meiner Anwendung implementiert haben kann, entschied ich mich, es als externe C++ - DLL zu verwenden. Bitte beachten Sie, dass ich Blowfish.NET und alle anderen ausprobiert habe, das Problem ist, dass ich Code von C++ in C# übersetze und der C# -Code genau dasselbe tun muss wie der C++ Code.Problem beim Aufruf einer C++ - DLL-Funktion von C#

Bisher:

--->C++ DLL source<---

Beachten Sie die exportierten Funktionen in dem Ende des Codes sind

C# -Code (Definition)

[DllImport("TestDLL.dll", EntryPoint = "Initkey" ,ExactSpelling = true , CallingConvention = CallingConvention.Cdecl)] 
    public static unsafe extern void Initkey(byte[] key); 

    [DllImport("TestDLL.dll", EntryPoint = "encode", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] 
    public static unsafe extern void encode(UInt32 *stream); 

C# -Code (Funktionsaufruf)

-initialize blowfish Schlüssel

UInt32[] keyarray = new UInt32[2]; 
//some code 
Extern.Initkey(Misc.ConvertFromUInt32Array(keyarray)); 
// 
// 
//Helper function used to convert a UInt32 array into Byte array. 
public static byte[] ConvertFromUInt32Array(UInt32[] array) 
{ 
    List<byte> results = new List<byte>(); 
    foreach (UInt32 value in array) 
    { 
     byte[] converted = BitConverter.GetBytes(value); 
     results.AddRange(converted); 
    } 
    return results.ToArray(); 
} 

-Encode die Daten.

  UInt32[] keyarray2 = new UInt32[2]; 
      //some code 
      unsafe 
      { 
       fixed (UInt32* LPBYTE = keyarray2) 
       { 
        Extern.encode(LPBYTE); 
       } 
      } 

Nach keyarray2 durch die Encode Funktion überschrieben wird, überprüfe ich die Werte in den C++ Code, indem sie zu entschlüsseln, ob alles in Ordnung ist, zu machen.

Nun, es ist nicht in Ordnung. Das ist mein Problem, deshalb bitte ich Sie um Ihre Hilfe. Die Werte sind unterschiedlich, wenn ich sie entschlüssle, aber wenn ich sie verschlüssle und sie in der C++ - Quelle entziffere, sind sie gleich. Der C++ - Code ist absolut derselbe, außer dass es keine DLL gibt, da der Code in C++ ist.

Könnte sein, wegen der Initialize-Funktion.Ich hatte vor ein paar Monaten gelesen, dass Arrays in C++ als Pointer übergeben werden. Ich glaube es nicht, aber selbst so - könnte das das Problem sein?

Ich kann keinen Hinweis finden. Ich habe mein Leben mit diesem Kugelfisch in C# verschwendet. Zumindest sollte diese Lösung funktionieren, aber es nicht - Warum?

+1

Sie haben Ihre Frau verschwendet? Etwas übertrieben IMO .. – Blorgbeard

Antwort

1

Um hinzuzufügen, was jachymko gesagt hat, überprüfen Sie auch die Dokumentation für BitConverter - Sie müssen sicherstellen, dass Sie den Schlüssel und die Daten in der Byte-Reihenfolge übergeben, die Sie beabsichtigten. Hinweis - In Ihrem vorherigen Thread habe ich Daten mit dem modifizierten Blowfish.NET-Verschlüssler erfolgreich verschlüsselt und mit dem Ergebnis Ihres C++ - Codes abgeglichen.

+0

@ Dave, Vielen Dank für Ihre Hilfe! Könnten Sie bitte die Quelle des modifizierten Blowfish.NET irgendwo hochladen? –

+0

Ja, ich werde die Quelle irgendwo hochladen. Es war ein C# 2008 Projekt und ein C++ 2008 Projekt - beide produzieren für mich die gleiche Ausgabe. –

+0

@Dave, danke! Bitte füge den Link hier ein, nicht in meinem alten Thread. Benutzst du meine C++ - Blowfish-Verschlüsselung, nicht irgendeine andere? –

0

Arrays in C und C++ werden als Zeiger übergeben. Semantik für Arrays in C# enthält eine zusätzliche Indirektionsebene. Ihr C# -Programm übergibt (wahrscheinlich) die Adresse einer Variablen, die die Adresse der Daten enthält.

Ich rang vor kurzem mit der Übergabe eines Arrays von Bytes von C# zu einer C-Funktion und musste die Daten in beiden Richtungen marshalieren. Es ist nicht offensichtlich für mich, dass dein Code das tut.

Besser als eine Erklärung, werde ich ein konkretes Beispiel nennen:

//extern "C" LIBEXIFWRAPPER_API void findEXIFtagValue(void * load, unsigned int tagID, char* buf, int bufLen); 
[DllImport("libexif-wrapper.dll")] 
unsafe public static extern IntPtr findEXIFtagValue([MarshalAs(UnmanagedType.SysUInt)]IntPtr load, int tagID, [MarshalAs(UnmanagedType.SysUInt)]IntPtr buf, int bufLen); 

Diese Funktion einen Zeiger auf undurchsichtige Daten akzeptiert, ein int und einen Byte-Array, in dem es eine Textzeichenfolge speichert.

Der folgende Ausschnitt zeigt, wie die Byte-Array wird erklärt, auf die C-Funktion übergeben, und die Ergebnisse extrahiert:

const int tagBuffer = 1024; 
IntPtr buf = Marshal.AllocHGlobal(tagBuffer); 

findEXIFtagValue(loader, (int)ExifTag.EXIF_TAG_DATE_TIME, buf, tagBuffer); 
string s = Marshal.PtrToStringAnsi(buf); 

Hinweis, dass das Argument in dem Prototyp gemarshallte und gemarshallte erneut das Ergebnis abzurufen.

Nichts davon war für mich besonders offensichtlich. Es scheint, dass IntPtr das C# -Aquivalent von void * ist, außer dass ich eine SysUInt verwenden musste, um ein (C) void * zu verwalten. Der Zeiger auf das Byte-Array wird als SysUInt gemarshallt.

(von C# Noob)

HTH

0

Mai werden Sie sollten mit ref für Zeiger und out für Funktionen versuchen, die Daten durch ein Argument zurück. Lass es mich wissen, wenn das funktioniert. Vielen Dank.

1

Ist Ihnen bekannt, dass Sie eine temporäre Instanz initialisieren, die zu dem Zeitpunkt zerstört wird, zu dem die Initkey-Funktion zurückkehrt? Sie sollten das Ganze in einer Funktion kombinieren oder den cBlowfish auf dem Heap erstellen und den Zeiger auf den C# -Code zurückgeben (er kann ihn als opakes IntPtr behandeln).

Darüber hinaus müssen Sie hier nicht unsicher verwenden. Übergeben Sie einfach das UInt32 [] direkt.

Verwandte Themen