错误:在C#中调用C ++ DLL函数 [英] Error: Calling C++ dll function in C#

查看:108
本文介绍了错误:在C#中调用C ++ DLL函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在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 as IntPtrs - 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函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆