C++ Datentypen VS. VB.Net Datenypen (DLL Aufruf)



  • Hi,

    Frage, ist folgendes überhaupt möglich?
    In VB.net wird eine c++ DLL aufgerufen (Vorgabe!):

    Private Declare Function Funktionsname Lib "C:\Dokumente und Einstellungen\xxxx\Desktop\dllVersuch\Debug\dllVersuch.dll" Alias "_Funktionsname@16" (ByVal text As String, zahl1 As Long, zahl2 As Long, ByVal Zahl3 As Long) As Long
    

    Man achte auf den Alias-Name "_Funktionsname@16" der ja Parameter von 16 Bytes erwartet.

    Ich soll nun diese DLL in C++ nachbasteln, und hatte an sowas gedacht:

    extern "C" __declspec(dllexport) __int64 _stdcall Funktionsname(wchar_t* xml, __int64 written, __int64 left, __int64 next)
    {
    	return written;
    }
    

    Wenn ich diese DLL mit dumpbin.exe aufrufe, zeigt er mir an, dass die Funktion _Funktionsname@28 exportiert wird 🙄
    Das liegt daran, dass __int64 8 byte groß ist und wchar_t* 4 byte (3 mal 8 + 4 = 28) ... Aber genau diese Typen muss ich doch verwenden, damit es zu keinem Typkonflikt in der VB.net Anwendung kommt... In der Vorgabe heißt die Funktion jedoch "_Funktionsname@16"!
    - Warum nur @16 ? Wie soll das gehn? ^^
    - Hat es vielleicht damit etwas zu tun, dass in dem DLL-Funktionsaufruf in VB.net zweimal "ByVal" und zweimal nichts angegeben ist?

    Hoffe ihr könnt mir schnellstmöglich helfen 🙂

    Grüße,
    crz



  • Der Datentyp System.Int64 (Long in VB) kann nicht by-value gemarshaled werden, und wird (auch bei der Angabe ByVal) immer als Pointer übergeben. Dann hättest Du deine 4x4 = 16 Bytes.



  • LordJaxom schrieb:

    Der Datentyp System.Int64 (Long in VB) kann nicht by-value gemarshaled werden, und wird (auch bei der Angabe ByVal) immer als Pointer übergeben. Dann hättest Du deine 4x4 = 16 Bytes.

    Also indem ich folgendes schreibe?

    extern "C" __declspec(dllexport) __int64* _stdcall Funktionsname(wchar_t* xml, __int64* written, __int64* left, __int64* next)
    

    Dann erhalte ich folgende Fehlermeldung:
    Ein Aufruf an die PInvoke-Funktion "TestKonsole1!TestKonsole1.Module1::Funktionsname" hat das Gleichgewicht des Stapels gestört. Wahrscheinlich stimmt die verwaltete PInvoke-Signatur nicht mit der nicht verwalteten Zielsignatur überein. Überprüfen Sie, ob die Aufrufkonvention und die Parameter der PInvoke-Signatur mit der nicht verwalteten Zielsignatur übereinstimmen.



  • Also zunächst vergiss, was ich im letzten Posting sagte. Entgegen der Angaben in http://msdn.microsoft.com/de-de/library/aa446536.aspx werden Longs offenbar doch problemlos by-value übergeben.

    Ich denke, Du hast hier einfach nur ein Namensproblem. Die Signatur der VB-Funktion (im Deinem ersten Posting) hat 28 Byte, auch wenn die Funktion @16 heißt. Sie könnte auch @HansDieter heißen, und hätte immernoch 28 Byte.

    Wenn Du also die Funktion mit genau dieser Signatur in C++ nachprogrammieren möchtest, benenne den Aliasnamen in VB.NET in @28 um. Folgendes Programm funktioniert:

    extern "C" __declspec(dllexport) __int64 _stdcall Funktionsname(wchar_t* xml, __int64 written, __int64 left, __int64 next) 
    {
    	return next;
    }
    
    Module Module1
    
        Private Declare Function Funktionsname Lib "PInvokeC.dll" Alias "_Funktionsname@28" (ByVal text As String, ByVal zahl1 As Long, ByVal zahl2 As Long, ByVal Zahl3 As Long) As Long
    
        Sub Main()
    
            Dim result As Long = Funktionsname("Hallo", 123, 456, 789)
            System.Console.WriteLine(result)
    
        End Sub
    
    End Module
    

    Kann es sein, dass die Funktion ursprünglich aus VB6 kommt und von einem Assistenten nach VB.NET konvertiert wurde? Denn in VB6 hatte Long nur 4 Bytes.



  • Hey LordJaxom,

    wow danke schonmal für die Mühe die du dir machst!
    Also "_Funktionsname@16" ist eine Vorgabe (ist eine Aufgabe aus der Ausbildung)... Daran darf/soll ich also eigentlich nichts ändern 😞

    Kann es sein, dass die Funktion ursprünglich aus VB6 kommt und von einem Assistenten nach VB.NET konvertiert wurde? Denn in VB6 hatte Long nur 4 Bytes.

    Daaaas kann natürlich sein... Wie kann ich das herausfinden, wenn ich nicht nachfragen darf?

    Danke nochmal



  • LordJaxom schrieb:

    Ich denke, Du hast hier einfach nur ein Namensproblem. Die Signatur der VB-Funktion (im Deinem ersten Posting) hat 28 Byte, auch wenn die Funktion @16 heißt. Sie könnte auch @HansDieter heißen, und hätte immernoch 28 Byte.

    Sicher, dass das plausibel ist? Der Name ist doch nicht willkürlich, sondern vom Compiler genau aufgrund ihrer Signatur gewählt worden.



  • Bashar schrieb:

    LordJaxom schrieb:

    Ich denke, Du hast hier einfach nur ein Namensproblem. Die Signatur der VB-Funktion (im Deinem ersten Posting) hat 28 Byte, auch wenn die Funktion @16 heißt. Sie könnte auch @HansDieter heißen, und hätte immernoch 28 Byte.

    Sicher, dass das plausibel ist? Der Name ist doch nicht willkürlich, sondern vom Compiler genau aufgrund ihrer Signatur gewählt worden.

    Meinerseits etwas unglücklich ausgedrückt. Ich wollte damit sagen, dass, wenn die Signatur 28 Bytes ergibt, daran auch der Name der Funktion "@16" nichts ändert. Und in diesem Fall vergibt der Compiler für die von mir angegebene Funktion, die zu 100% zu der PInvoke-Signatur passt, @28. Deshalb kann eigentlich nur a) der Alias falsch oder b) die Signatur aus einer älteren VB-Version sein.

    EDIT: Hiernach stand Mist.



  • a) würde bedeuten, dass jemand nachträglich den Namen in der DLL verändert hat, oder?
    b) würde heißen, dass das Programm seit der Portierung auf VB.NET nicht mehr funktioniert hat.

    Ich würd jetzt den Disassembler auf die DLL loslassen 🙂


Anmelden zum Antworten