日期:2014-05-17  浏览次数:20651 次

C#调用DLL,实在找不到问题出在哪里了
在网上看了许多关于C#调用C/C++编写的DLL文件的帖子,但是都没有能解决我的问题,有点抓狂了......

1. 目前的程序是在别人的程序的基础上进行的“修修补补”,该程序是使用DLL文件进行的二次开发。

2. 可能出问题的地方:
(2.1)C#调用的代码是:
C# code

[DllImport("MyFunction.dll",EntryPoint="GetPortInfo")]
public static extern UInt32 GetPortInfo(UInt32 Device, Byte Num, IntPtr pPortInfo);


(2.2)C代码是:
C/C++ code

UInt32 GetPortInfo( UInt32 hDevice, unsigned char num, PortInfo& pPortInfo );


(2.3)其中,PortInfo数据结构是:
在C#中的写法:
C# code

[StructLayout(LayoutKind.Sequential,Pack=1)]
public struct port
{
    [MarshalAs(UnmanagedType.ByValArray,SizeConst=6)]
    public Byte[] mac;
    [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)]
    public Byte[] ip;
    [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)]
    public Byte[] mask;
    [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)]
    public Byte[] gage;
    [MarshalAs(UnmanagedType.U4)]
    public Uint32 ArpReply;
    [MarshalAs(UnmanagedType.U4)]
    public Uint32 IcmpReply;
    [MarshalAs(UnmangeddType.U1)]
    public Byte IgmpEnable;
    [MarshalAs(UnmangeddType.U1)]
    public Byte MultiPauseEnable;
    [MarshalAs(UnmangeddType.U1)]
    public Byte DirectPauseEnable;
    [MarshalAs(UnmanagedType.ByValArray,SizeConst=6)]
    public Byte[] UserDefAddr;
}


在C++中的写法:
C/C++ code

struct PortInfo
{
    unsigned char mac[6];
    unsigned char ip[4];
    unsigned char mask[6];
    unsigned char gate[6];
    ArpReplayEnum ArpReply;
    IcmpReplyEnum IcmpReply;
    unsigned char IgmpEnable;
    unsigned char MultiPauseEnable;
    unsigned char DirectPauseEnable;
    unsigned char UserDefAddr[6];
}



3. 当调用该函数时报出的错误是:
用户代码未处理System.AccessViolationException
Message="尝试读取或者写入受保护的内存。这通常指示其他内存已损坏。

4. 碰到这个问题后,我先是上网搜索,有不少这样的帖子,我进行了一系列的排错:
(4.1)硬件损坏;
该程序是一个利用C#进行二次开发的程序。我的机子上正好有改程序C++发行版软件,在硬件平台上运行后,一切正常,因此,我觉得可以排除这个可能性。
(4.2)DLL文件传入的参数类型与C#本身的数据类型有矛盾;
这是我看到的网上最流行的说法之一。
在我的电脑上保存有“目前我修改的这个程序”的原始版本,我运行原始版本的程序,没有出错。我有找了身边做这方面工作的同事帮我看了一下,认为参数没有问题。
(4.3)DLL文件放置的位置不正确。
我的DLL文件放在bin目录下,应该没有问题吧?
(4.4)DLL文件本身有问题。
我运行原始版本的C#程序,没有出错,我想应该可以排除当前的这个错误的可能性了吧?
(4.5)访问权限的问题。
我对比了原始版本的C#程序,和我现在的这个的Web配置文件,是一样的(因为实际上我是直接拷贝了原来的那个程序,然后再拷贝的程序上进行的修改)。因此,这个方面是否没有问题了?
(4.6)C++中的结构体的大小与C#中结构体的大小不一致。
我用VC6测试了一下:
sizeof(port) = 40;
在C#中,传递的参数IntPtr pPortInfo是这样定义的:
C# code

IntPtr pPortInfo = Marshal.AllocHGlobal(40);


因此,我对C#该数据结构做了修改,去掉了“Pack=1”,并添加了填充字节:
C# code

[StructLayout(LayoutKind.Sequential)]
public struct port
{
    [MarshalAs(UnmanagedType.ByValArray,SizeConst=6)]
    public Byte[] mac;
    [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)]
    public Byte[] ip;
    [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)]
    public Byte[] mask;
    [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)]
    public Byte[] gage;
    public UInt16 pad1;
    [MarshalAs(UnmanagedType.U4)]
    public Uint32 ArpReply;
    [MarshalAs(UnmanagedType.U4)]
    public Uint32 IcmpReply;
    [