当前位置:编程学习 > C#/ASP.NET >>

c# 调用DLL(C++)提示“尝试读取或写入受保护的内存。这通常指示其他内存已损坏”

自己写了个DLL,另外建一个测试程序调用,不在同一个project里面。

代码如下:
DLL:

#define EX_FUNC extern "C" __declspec(dllexport)

typedef struct _VersionInfo
{
char cSWVersion;
char cHWVersion;
}VERSIONINFO, *PVERSIONINFO;

EX_FUNC int Reader_Initialize(short nPort, long nBaud, PVERSIONINFO pVersionInfo);


C#
    class Reader
    {
        public struct VersionInfo
        {
            public char cSWVersion;
            public char cHWVersion;
        }
        [DllImport("LibReader.dll")]
        public static extern int Reader_Initialize(short nPort, long nBaud, ref VersionInfo pVersionInfo);
        [DllImport("LibReader.dll")]
        public static extern int Test();
    }

调用:
            Reader.VersionInfo vi = new Reader.VersionInfo();
            Reader.Reader_Initialize(1, 9600, ref vi);


调用Reader_Initialize就会提示“尝试读取或写入受保护的内存。这通常指示其他内存已损坏”。
一直以为是struct的原因,后来发现在DLL Reader_Initialize中,只要对struct赋值就会出现以上提示。删除掉
pVersionInfo->cHWVersion = '0';
就没事。


这是什么原因? --------------------编程问答-------------------- 应该是你的版本问题吧 --------------------编程问答-------------------- c++中的char是1个字节,c#中的char是2个字节,应该换成byte。
c++在windows中的long是32位,c#的long是64位,这个也不准确。
vc函数默认的清理堆栈方式不是_stdcall,c# p/invoke调用时默认的是_stdcall,这个也不准确。int Reader_Initialize应该改成int _stdcall Reader_Initialize,或者c#调用时声明为_cdecl --------------------编程问答-------------------- 解决了,感谢2楼!
C#中把struct定义里面的char改为byte,函数声明里面的long改为Int32就OK了。看来还要找时间整理以下C++和C#的数据类型。

堆栈方式没改,还是使用public static extern int Reader_Initialize,暂时没发现什么问题。就不知道有没有后患了,呵呵。
--------------------编程问答-------------------- 关注,学习 --------------------编程问答--------------------
引用 2 楼 lizhibin11 的回复:
c++中的char是1个字节,c#中的char是2个字节,应该换成byte。
……


楼主,这样做是有问题的,你改成这样,只是不出错而已,往往得不到正确值!
byte与char的值范围不一样,char在net是uncode方式,确实占两个字节,但这些区别有互操作来处理:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct VersionInfo
  {
  public char cSWVersion;
  public char cHWVersion;
  }
--------------------编程问答-------------------- C/C++,WIN32,C#数据类型对应关系

WIN32 C/C++ C# 托管类名 说明
HANDLE void* IntPtr System.IntPtr
在 32 位 Windows 操作系统上为 32 位
BYTE unsigned char byte System.Byte
8 位
SHORT short short System.Int16
16 位
WORD unsigned short ushort System.UInt16
16 位
INT int int System.Int32
32 位
UINT unsigned int uint System.UInt32
32 位
LONG long int System.Int32
32 位
BOOL long int System.Int32
32 位
DWORD unsigned long uint System.UInt32
32 位
ULONG unsigned long uint System.UInt32
32 位
CHAR char char System.Char
用 ANSI 修饰。
LPSTR char* System.String 或 System.Text.StringBuilder
用 ANSI 修饰。
LPCSTR Const char* System.String 或 System.Text.StringBuilder
用 ANSI 修饰。
LPWSTR wchar_t* System.String 或 System.Text.StringBuilder
用 Unicode 修饰。
LPCWSTR Const wchar_t* System.String 或 System.Text.StringBuilder
用 Unicode 修饰。
FLOAT Float single System.Single
32 位
DOUBLE Double double System.Double
64 位

--------------------编程问答-------------------- 按楼上的来说, c# 和c++的格式还是有区别的吧
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,