【发布时间】:2015-02-10 21:37:01
【问题描述】:
我需要使用C#来控制一个带有C++ DLL的测试模块,下面是最初在C++头文件中定义的结构和init函数
typedef unsigned char uint8_t;
typedef unsigned long uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char bool_t;
typedef signed short int16_t;
typedef signed char int8_t;
typedef signed long int32_t;
#define ER 0x2
#define BS 0x4000
typedef enum {
nI2C,
nSPI,
nUSB,
nSDIO
} mBus;
typedef uint8_t cAddr;
typedef enum {
nCPHA0=0,
nCPHA1
} mPhase;
typedef enum {
nCPOL0=0,
nCPOL1
} mSpiPol;
typedef struct {
mPhase cPha;
mSpiPol cPol;
} mSpiCfg;
typedef struct {
uint8_t xo;
bool_t init_bus_only;
uint32_t zone;
mBus bustype;
mBus transporttype;
cAddr i2cAddr;
mSpiCfg spiCfg;
bool_t use_pmu;
} mInitCfg;
typedef enum {
OK = 0,
FAIL = -1,
BUS_ALREADY_LOADED = -2,
BUS_TYPE_UNKNOWN = -3,
BUS_LOAD_LIBRARY_FAIL = -4,
BUS_GET_PROC_FAIL = -5,
BUS_INIT_FAIL = -6,
Err_CHIP_INIT = -7
} retCode;
typedef struct {
mInitCfg cfg;
} mDrvIn;
__declspec(dllexport) retCode cp_init(mDrvIn * inp);
在 C++ 中,它的调用如下所示
static void init(void)
{
mDrvIn di;
retCode rc;
memset(&di, 0, sizeof(mDrvIn));
di.cfg.bustype = nI2C;
di.cfg.init_bus_only = 1;
di.cfg.transporttype = di.cfg.bustype;
di.cfg.zone = ER | BS;
rc = cp_init(&di);
if(rc < 0) {
printf("Failed to initialize. Error code %d: %s", rc, to_string(rc));
return;
}
}
我在调用 DLL 函数时使用下面的 C# 结构
using cAddr = System.Byte;
public enum mBus
{
nI2C,
nSPI,
nUSB,
nSDIO
};
public enum mPhase
{
nCPHA0 = 0,
nCPHA1
};
public enum mSpiPol
{
nCPOL0 = 0,
nCPOL1
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct mSpiCfg
{
public mPhase cPha;
public mSpiPol cPol;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct mInitCfg
{
public byte xo;
public byte init_bus_only;
public uint zone;
public mBus bustype;
public mBus transporttype;
public cAddr i2cAddr;
public mSpiCfg spiCfg;
public byte use_pmu;
};
public enum retCode
{
OK = 0,
FAIL = -1,
BUS_ALREADY_LOADED = -2,
BUS_TYPE_UNKNOWN = -3,
BUS_LOAD_LIBRARY_FAIL = -4,
BUS_GET_PROC_FAIL = -5,
BUS_INIT_FAIL = -6,
Err_CHIP_INIT = -7
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct mDrvIn
{
public mInitCfg cfg;
};
[DllImport("mdrv.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern retCode cp_init(ref mDrvIn inp);
我使用下面的代码来初始化
public static void init()
{
mDrvIn di = new mDrvIn();
retCode rc = new retCode();
di.cfg.bustype = mBus.nI2C;
di.cfg.init_bus_only = 1;
di.cfg.transporttype = di.cfg.bustype;
di.cfg.zone = 0x2 | 0x4000;
rc = cp_init(ref di);
if (rc < 0)
{
Console.Write("Failed to initialize. Error code: " + rc);
return;
}
}
问题是使用C++初始化模块正常工作,而C#不行,总是返回错误码-5(表示总线错误:未能在DLL中枚举总线函数),结构的指针似乎成功传递给 DLL 没有错误,因此我想知道我在 C# 中转换的结构是否有问题,因此传递给 C++ 函数的参数已损坏或其他原因,有人可以帮我解决这个问题吗?提前致谢。
【问题讨论】:
-
检查您的 C# 类型的
Marshal.SizeOf()并比较您的 C++ 类型的sizeof()。 -
printf("size => %d",di) 这给了我 256 Marshal.SizeOf(di) 给了我 32 但不知道是什么造成了这种差异?即使将 bool_t 的 int 更改为 byte,我的 C# 结构仍然是错误的?
-
没有区别,
sizeof返回位和Marshal.SizeOf字节,所以是一样的。 -
谢谢,有没有其他调试技巧可以用来找出导致我的 C# 结构与 C++ 不同的原因?
标签: c# c++ pointers dll struct