在库的C ++头文件中有以下代码
#define STR_DATE 24+1
#define STR_SIZE 32+1
#define STR_SSIZE 64+1
#define STR_MSIZE 128+1
#define STR_LSIZE 1024+1
#define STR_IPSIZE 15+1
#define STR_MOD_SIZE 20+1
#define STR_AGESIZE 4+1
#define STR_GENDERSIZE 1+1
typedef struct ADO_PINFO{
char P_ID[STR_SSIZE];
char F_Name[STR_SSIZE];
char M_Name[STR_SSIZE];
char L_Name[STR_SSIZE];
char Reg_Num[STR_SSIZE];
UINT nGender;
UINT nAge;
COleDateTime BirthDay;
char csBirthDay[STR_SIZE];
COleDateTime V_Date;
char csV_Date[STR_SIZE];
char Address[_MAX_PATH];
char SubAddress[_MAX_PATH];
char Telephone[STR_SIZE];
char H_Phone[STR_SIZE];
char csMail[STR_SSIZE];
char csPicName[_MAX_PATH];
COleDateTime InDate;
char csInDate[STR_SIZE];
}*PADO_PINFO;
_ADODLL long ADO_AddPatientData(const ADO_PINFO &pPatientInfo);
我正在尝试将dll导入到我的C#应用程序中:
[StructLayout(LayoutKind.Sequential)]
public struct ADO_PINFO
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string P_ID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string F_Name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string M_Name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string L_Name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string Reg_Num;
public uint nGender;
public uint nAge;
public DateTime BirthDay;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)] public string csBirthDay;
public DateTime V_Date;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)] public string csV_Date;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string Address;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string SubAddress;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)] public string Telephone;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)] public string H_Phone;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string csMail;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string csPicName;
public DateTime InDate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)] public string csInDate;
}
public class VatechLibrary
{
[DllImport("AdodllE.dll")]
public static extern long ADO_AddPatientData(ref ADO_PINFO patientInfo);
}
但是当我尝试co调用它时:
var pInfo = new ADO_PINFO();
pInfo.P_ID = "77";
pInfo.F_Name = "name";
var res = VatechLibrary.ADO_AddPatientData(ref pInfo);
我收到AccessViolationException。我做错了什么?
答案 0 :(得分:2)
我可以看到的问题:
COleDateTime
字段的编组错误。那是因为COleDateTime
是一个C ++类,它们根本不是二进制互操作的有效类型。并且.net DateTime
肯定不匹配。这肯定是您违反访问权限的来源。long
,在Windows上为32位宽。所以你的C#函数声明是错误的,因为C#long
是64位宽。将C#中的返回值更改为int
。stdcall
。 C ++函数的调用约定是什么?这大概包含在_ADODLL
中。您需要检查它是stdcall
。如果未指定调用约定,则为cdecl
。 COleDateTime
的问题在这里很重要。其他很容易修复。 COleDateTime
不是这样。您可以更改C ++代码以接受日期的互操作友好表示。如果您无法更改C ++代码来处理第1项的问题,那么您的解决方案将涉及编写混合模式C ++ / CLI包装器。
答案 1 :(得分:0)
来自UnmanagedType.ByValTStr
的文档:
用于出现在a中的内嵌式固定长度字符数组 结构体。与ByValTStr一起使用的字符类型由 System.Runtime.InteropServices.CharSet的参数 应用了System.Runtime.InteropServices.StructLayoutAttribute属性 到包含结构。总是使用 MarshalAsAttribute.SizeConst字段指示数组的大小。 .NET Framework ByValTStr类型的行为类似于C风格的固定大小字符串 在结构内部(例如,char s [5])。
你的字符集是什么?我的猜测是unicode。
答案 2 :(得分:0)
如果我猜测我会说你需要在C#strcuture声明中的struct layout上指定字符编码为ANSI。 ByValTStr将携带包含结构的编码并使用char基于您的C ++结构我认为您需要将它们编码为Ansi。
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
来自MSDN http://msdn.microsoft.com/en-us/library/s9ts558h(v=vs.110).aspx
UnmanagedType.ByValTStr
固定长度的字符数组;数组的类型由。确定 包含结构的字符集。
答案 3 :(得分:0)
您可能还需要添加Pack=1 to your StructLayout attribute.
大多数字符串/数组的长度都是奇数个字节,默认情况下,.NET会将每个字符串/数组填充到偶数字节边界。
答案 4 :(得分:0)
你应该检查结构,类型COleDateTime是一个C ++类,而不必创建一个直接互操作的属性。查看您需要访问的项目并重做布局。