日期:2014-05-18  浏览次数:20781 次

关于C#调用c++编写的DLL问题

我用C++编写了一个Player Information Database 以及相应的接口函数用于从外部操作数据库,我想要动态调用 .dll文件中的所有函数

我就拿其中几个函数做例子:
在Dll中
C/C++ code

#ifdef DB_EXPORTS
#define DB_API __declspec(dllexport)
#else
#define DB_API __declspec(dllimport)
#endif
         extern "C"
        {
    DB_API void DB_Init(void **DB);
    DB_API void DBDisplay(void *DB);
         }
    //用于初始化数据库
          void DB_Init(void **DB)
    {
        CPlayerDatabase *myDB = new CPlayerDatabase();
        myDB->init();
        *DB = myDB;
    }
         //用于打印数据库
    void DBDisplay(void *DB)
    {
        ((CPlayerDatabase*)DB)->Display();
    }


在C# 定义的接口类中,大家帮我看看我导入DLL的方法正确吗? 
C# code

class PlayerDataBase_API
{
    //因为这里是指针的指针,我觉得我的定义是错的
    [DllImport("CPlayerDataBaseDll.dll"), EntryPoint = "DB_Init"]
    public static extern void DB_Init(out IntPtr DB);
    [DllImport("CPlayerDataBaseDll.dll"), EntryPoint = "DBDisplay"]
    public static extern void DBDisplay(IntPtr DB);

}



在主函数中:
我用到了
IntPtr cpdb = Marshal.AllocHGlobal(0);
PlayerDatabase_API.DB_Init(out cpdb);
PlayerDatabase_API.DBDisplay(cpdb);
结果报错了。。。

因为我会用到很多DLL的函数,他们可以共用这个IntPtr cpdb 吗?如果是该怎么做? 还是像c++中对每个函数都要进行Load, GetProcAddress,Free.
这是我现在正在学的跨平台调用DLL,所以我还有很多问题,希望大家给我提点意见,谢谢各位。

------解决方案--------------------
建议你把 void **DB 直接定义成 int,然后内部强制转换试试看。
------解决方案--------------------
因為是二級指針
所以應該是
IntPtr cpdb = Marshal.AllocHGlobal(0);
PlayerDatabase_API.DB_Init(new IntPtr(cpdb));
應該可以不用使用[out, ref]關鍵字了,所以宣告時也不用使用[out, ref]
------解决方案--------------------
你在C中定義的DBDisplay函數不是二重指針,所以只要寫成
 Intptr c2 = Marshal.AllocHGlobal(0);
PlayerDatabase_API.DBDisplay(c2);
即可。
當然,你可以不用重覆定義Intptr c2 = Marshal.AllocHGlobal(0);
你可以使用原有的IntPtr cpdb = Marshal.AllocHGlobal(0);
即可。

引用:

建议你把 void **DB 直接定义成 int,然后内部强制转换试试看。


應該是指在你寫的C代碼(API)中,將
void DB_Init(void **DB)
{
CPlayerDatabase *myDB = new CPlayerDatabase();
myDB->init();
*DB = myDB;
}
改成
int DB_Init(void **DB)
{
.....
return ....
}
這樣你在平台調用時就可以用你原來的方式,且用int來宣告變數即可。(我猜的啦﹗)