2010-11-22 10 views
2

Ich habe total versagt diese wirklich einfache P/Invoke.Marshalling einfache Zeichenfolge in C#

[System.Runtime.InteropServices.DllImport(
     "temp.dll" 
    )] 
    private static extern System.IntPtr parser_alloc(); 

    [System.Runtime.InteropServices.DllImport(
     "temp.dll", 
     CharSet = System.Runtime.InteropServices.CharSet.Ansi 
    )] 
    private static extern void parser_add_file(
     System.IntPtr p, 
     [MarshalAs(UnmanagedType.LPStr)]string f, 
     [MarshalAs(UnmanagedType.LPStr)]string s); 

    [System.Runtime.InteropServices.DllImport(
     "temp.dll" 
    )] 
    private static extern void parser_free(
     System.IntPtr p); 

    [System.Runtime.InteropServices.DllImport(
     "temp.dll" 
    )] 
    private static extern void parser_emit_results(
     System.IntPtr p); 

    [System.Runtime.InteropServices.DllImport(
     "temp.dll", 
     CharSet = System.Runtime.InteropServices.CharSet.Ansi 
    )] 
    private static extern void parser_file_updated(
     System.IntPtr p, 
     [MarshalAs(UnmanagedType.LPStr)]string f, 
     int offset, 
     int added); 

Erstellen des Objekts scheint gut zu gehen. Wenn ich jedoch versuche, parser_add_file aufzurufen, sagt mir die Laufzeit, dass ich eine nicht übereinstimmende Signatur habe. Dies ist meine vorhandenen C++ Code:

class Parser { 
public: 
    void add_file(std::string filename, std::string source) { 
     std::cout << "add_file | " << filename << " | " << source << "\n"; 
    } 
    void clear_contents() { 
     std::cout << "clear_contents\n"; 
    } 
    void emit_results() { 
     std::cout << "emit_results\n"; 
    } 
    void file_updated(std::string filename, int offset, int added) { 
     std::cout << "file_updated | " << filename << " | " << offset << " | " << added << "\n"; 
     // added should be negative to signify removing 
    } 
    Parser() { 
     std::cout << "I made a Parser!\n"; 
    } 
}; 

extern "C" __declspec(dllexport) Parser* parser_alloc() { 
    return new Parser; 
}; 

extern "C" __declspec(dllexport) void parser_add_file(Parser* p, const char* filename, const char* string) { 
    p->add_file(filename, string); 
} 

extern "C" __declspec(dllexport) void parser_free(Parser* p) { 
    delete p; 
} 

extern "C" __declspec(dllexport) void parser_emit_results(Parser* p) { 
    p->emit_results(); 
} 

extern "C" __declspec(dllexport) void parser_file_updated(Parser* p, const char* filename, int offset, int added) { 
    p->file_updated(filename, offset, added); 
} 

Soll ich nur P/Invoke überspringen und für diesen Job zu C++/CLI gehen?

Antwort

1

Stellt sich heraus, dass ich die Aufrufkonvention manuell auf cdecl festlegen musste - der Standardwert ist Stdcall.

0

Wenn Sie Zugriff auf die C++ - Quelle haben (was so aussieht), können Sie die Aufrufkonvention auch auf der C++ - Deklarationsebene ändern. Hier ist eine Beispielfunktion für eine Bibliothek, die ich schrieb:

int _stdcall GeoConvertLatLongToUTM(double latitude, double longitude, char *szOutput)