我正在将一些c ++ dll导入到c#项目中,我正在使用visual studio 2010.我已经成功导入了使用内置类型的函数,但是当我尝试处理结构时遇到错误。这是一个简单的例子:
c ++代码
typedef long int TDate;
typedef struct _TMDYDate
{
long month; /* In range [1,12] */
long day; /* In range [1-31] */
long year; /* In range [1600-] */
} TMonthDayYear;
int JpmcdsDateToMDY
(TDate date, /* (I) TDate format */
TMonthDayYear *mdyDate);
我已将c#翻译为:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct TMonthDayYear {
public int month;
public int day;
public int year;
}
public partial class NativeMethods {
[System.Runtime.InteropServices.DllImportAttribute("MyDll.dll", EntryPoint="JpmcdsDateToMDY")]
public static extern int JpmcdsDateToMDY(int date, ref TMonthDayYear mdyDate) ;
}
当我尝试在我的测试程序中运行该函数时,我收到此错误:
未处理的异常:System.AccessViolationException:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。在CsharpWrapper.NativeMethods.JpmcdsDateToMDY(Int32日期,TMonthDayYear& mdy Date)
结构是在堆栈中声明的,我认为(也许)是问题但是我仍然得到相同的错误,即使我已经将TMonthDayYear更改为类。
我做错了什么?
谢谢你的帮助。
答案 0 :(得分:3)
您必须在[DllImport]属性中使用CallingConvention属性,这是Cdecl,因为您在本机函数声明中没有使用__stdcall。虽然这是错的,但对AV来说并不是一个很好的解释。你需要调试C代码,AV建议它有一个指针错误。 Project + Properties,Debug,勾选“启用非托管代码调试”并在C函数上设置断点。
坦率地说,像这样的日期转换应该用纯C#编写。
答案 1 :(得分:0)
TDate
类型为long int
,但在托管代码中,它表示为int32而不是int64。
答案 2 :(得分:0)
它可能相关也可能不相关,但您需要mdyDate参数上的[OutAttribute]
才能写入。
答案 3 :(得分:0)
如果您是c ++中的习惯用户,您可能熟悉直接寻址内存的指针。您的错误看起来像是内存读/写保护相关的问题。
这是C#的标准性质所禁止的,你必须将编译器置于不安全模式。
如果您在c#中编码不安全,则必须将代码置于不安全模式。
unsafe
{
// unsafe things
}
unsafe class Class1 {}
static unsafe void someMethod ( int* cpi, int lngth) {...}
您还必须检查项目配置(构建 -tab)并添加“允许不安全代码”的复选框。
如果我滚动一些太明显的信息,我道歉。我还要说明,如果情况是C#要解决内存问题,那么这个评论只有意义。