问题描述
我想在C ++从C#DLL使用的功能,但我得到了一个错误:尝试读取或写入受保护的内存这通常是指示其他内存已损坏
$ B ?$ b
任何人都知道如何解决。
下面是C ++的功能:
的typedef无效* DGNHandle;
__declspec(dllexport)的DGNHandle CPL_DLL DGNOpen(为const char *,INT);
__declspec(dllexport)的DGNElemCore CPL_DLL * DGNReadElement(DGNHandle)
下面是在C ++结构:
typedef结构{
INT抵消;
INT大小;
INT element_id; / *<!;编号(从零开始)* /
INT STYPE; / *<!;结构类型:(DGNST_ *)* /
INT水平; / *<!;元级别:0-63 * /
int型的; / *<!;元素类型(DGNT_)* /
INT复杂; / *<!;是复杂的元素? * /
INT删除; / *<!;被删除的元素? * /
INT graphic_group; / *<!;图形组号* /
INT性能; / *<!;属性:DGNPF_标志的ORing * /
INT色; / *<!;显色指数(0-255)* /
INT重; / *<!;线宽(0-31)* /
INT的风格; / *<!;线型:一个DGNS_ *值* /
INT attr_bytes的; / *<!;属性数据,通常是零字节。 * /
无符号字符* attr_data; / *<!;原始属性数据* /
INT raw_bytes; / *<!;原始数据,通常是零字节。 * /
无符号字符* raw_data; / *<!;所有原始元素数据包括报头。 * /
} DGNElemCore;
和下面的转换代码是在C#中:
[StructLayout(LayoutKind.Sequential)]
公共类DGNElemCore
{
公众诠释attr_bytes;
公共字节[] attr_data;
公众诠释色彩;
公众诠释复杂的;
公众诠释删除;
公众诠释element_id;
公众诠释graphic_group;
公众诠释的水平;
公众诠释抵消;
公众诠释性能;
公众诠释raw_bytes;
公共字节[] raw_data;
公众诠释大小;
公众诠释风格;
公众诠释STYPE;
公众诠释类型;
公众诠释权重;
}
函数[DllImport(DgnLib.dll,入口点=DGNOpen)]
公共静态外部的IntPtr DGNOpen(字符串文件名,诠释bUpdate);
函数[DllImport(DgnLib.dll,入口点=DGNReadElement)]
公共静态外部DGNElemCore DGNReadElement(IntPtr的DGNHandle)
代码来进行测试:
DGNElemCore元素=新DGNElemCore();
元素= DgnFile.DGNReadElement(dgnFile.oDgnFile)** //引发错误**
您的 DGNElemCore
在C#代码是错误的声明 - 它需要你的C结构(尤其是大小)完全匹配,否则编组代码将尝试封送不正确的内存。一个例子定义,将工作(如不引起编组过程中出现问题)将以下
[StructLayout(LayoutKind.Sequential) ]
公共类DGNElemCore
{
INT抵消;
INT大小;
INT element_id;
INT STYPE;
INT水平;
int型的;
INT复杂;
INT删除;
INT graphic_group;
INT性能;
INT色;
INT重;
INT的风格;
INT attr_bytes;
IntPtr的attr_data;
INT raw_bytes;
IntPtr的raw_data;
}
尤其
请注意
- 在C#类成员的顺序匹配在C结构(尽管这在调用你的函数,当访问编组结构的成员时,它会给你不正确的值不会导致错误)
- 的
的char *
字段被编组为的IntPtr
秒 - 试图元帅指针以数组一样数组不是指针较大,导致编组试图集结更多的内存比可用阵列将默认情况下不工作。
此外,我注意到,您的p / Invoke方法的声明是错误的。在 DGNOpen
函数返回结构本身(而不是一个指针),因此应该看起来更像下面。
公共静态外部DGNElemCore DGNOpen(字符串文件名,INT bUpdate);
的
DGNReadElement
函数接受一个结构(未一个指针),并返回一个指向该strucut(不是结构),因此应该看起来更像这个
公共静态外部的IntPtr DGNReadElement(DGNHandle手柄);
属性可以被用来改变该编组作品,这又可以用于改变的方式这些方法的签名,但是如果你这样做,你必须要小心,以确保编组仍然会匹配到你的C ++函数声明。
I am trying to use functions in C++ dll from C#, but I got an error: "attempt to read or write protected memory. This is often indication that other memory is corrupt"
Anyone know how to fix ?
Here is C++ functions:
typedef void *DGNHandle;
__declspec(dllexport) DGNHandle CPL_DLL DGNOpen( const char *, int );
__declspec(dllexport) DGNElemCore CPL_DLL *DGNReadElement( DGNHandle )
Here is structure in C++:
typedef struct {
int offset;
int size;
int element_id; /*!< Element number (zero based) */
int stype; /*!< Structure type: (DGNST_*) */
int level; /*!< Element Level: 0-63 */
int type; /*!< Element type (DGNT_) */
int complex; /*!< Is element complex? */
int deleted; /*!< Is element deleted? */
int graphic_group; /*!< Graphic group number */
int properties; /*!< Properties: ORing of DGNPF_ flags */
int color; /*!< Color index (0-255) */
int weight; /*!< Line Weight (0-31) */
int style; /*!< Line Style: One of DGNS_* values */
int attr_bytes; /*!< Bytes of attribute data, usually zero. */
unsigned char *attr_data; /*!< Raw attribute data */
int raw_bytes; /*!< Bytes of raw data, usually zero. */
unsigned char *raw_data; /*!< All raw element data including header. */
} DGNElemCore;
And below converted codes are in C#:
[StructLayout(LayoutKind.Sequential )]
public class DGNElemCore
{
public int attr_bytes;
public byte[] attr_data;
public int color;
public int complex;
public int deleted;
public int element_id;
public int graphic_group;
public int level;
public int offset;
public int properties;
public int raw_bytes;
public byte[] raw_data;
public int size;
public int style;
public int stype;
public int type;
public int weight;
}
[DllImport("DgnLib.dll", EntryPoint = "DGNOpen")]
public static extern IntPtr DGNOpen(string fileName, int bUpdate);
[DllImport("DgnLib.dll", EntryPoint = "DGNReadElement")]
public static extern DGNElemCore DGNReadElement(IntPtr DGNHandle)
Codes for testing:
DGNElemCore element = new DGNElemCore();
element = DgnFile.DGNReadElement(dgnFile.oDgnFile) **//Throw error**
Your declaration of DGNElemCore
in your C# code is wrong - it needs to exactly match your C structure (especially in size) as otherwise the marshalling code will attempt to marshal memory incorrectly. An example definition which will work (as in not cause problems during marshalling) would be the following
[StructLayout(LayoutKind.Sequential )]
public class DGNElemCore
{
int offset;
int size;
int element_id;
int stype;
int level;
int type;
int complex;
int deleted;
int graphic_group;
int properties;
int color;
int weight;
int style;
int attr_bytes;
IntPtr attr_data;
int raw_bytes;
IntPtr raw_data;
}
Note in particular
- The order of members in the C# classes match those in the C struct (although this wont cause an error when calling your function it will give you incorrect values when accessing the members of the marshalled struct)
- The
char*
fields are marshalled asIntPtr
s - attempting to marshal pointers to arrays as arrays won't work by default as arrays are larger than pointers, resulting in the marshaller attempting to marshal more memory than is available.
Also I've noticed that your P/Invoke method declarations are wrong. The DGNOpen
function returns the structure itself (not a pointer) and so should look more like the following.
public static extern DGNElemCore DGNOpen(string fileName, int bUpdate);
The DGNReadElement
function accepts a struct (not a pointer) and returns a pointer to that strucut (not a struct) and so should look more like this
public static extern IntPtr DGNReadElement(DGNHandle handle);
Attributes can be used to change the way that the marshaller works, which can in turn be used to alter the signature of these methods, however if you do this you need to be careful to ensure that the marshalling will still match up to your C++ function declarations.
这篇关于错误:在C#中调用C ++ DLL函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!