2010-11-22 19 views
2

J'ai complètement échoué ce très simple P/Invoke.Marshalling chaîne simple en 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); 

La création de l'objet semble aller bien. Cependant, lorsque j'essaie d'appeler parser_add_file, l'exécution me dit que j'ai une signature incompatible. Ceci est mon code C++ existant:

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); 
} 

Dois-je passer juste P/Invoke et aller à C++/CLI pour ce poste?

Répondre

1

Il s'avère que j'ai dû manuellement définir la convention d'appel à cdecl- la valeur par défaut est stdcall.

0

Si vous avez accès à la source C++ (ce que vous avez l'air de faire), vous pouvez également modifier la convention d'appel au niveau de la déclaration C++. Voici une fonction d'exemple pour une bibliothèque que j'ai écrite:

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