代码之家  ›  专栏  ›  技术社区  ›  Puppy

在C中编组简单字符串#

  •  2
  • Puppy  · 技术社区  · 14 年前

    我完全没有通过这个非常简单的P/Invoke。

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

    创建对象似乎很顺利。但是,当我尝试调用parser_add_文件时,运行时会告诉我签名不匹配。这是我现有的C++代码:

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

    我是否应该跳过p/Unjk并进入C++或CLI?

    2 回复  |  直到 14 年前
        1
  •  1
  •   Puppy    14 年前

    结果我不得不手动将调用约定设置为cdecl-默认值是stdcall。

        2
  •  0
  •   SRM    14 年前

    如果您有权访问c++源代码(看起来是这样),那么您也可以在c++声明级别更改调用约定。下面是我为一个库编写的函数示例:

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