开发一个控制LED显示屏的程序。其中需要调用厂家给的DLL中的函数。由于厂家给的开发手册很混乱,里面的内容的可信度不高(有的函数和用工具查看出来的函数名都不一致,有的函数本来没用,手册上却写着有用),只能参考他们给的例子。由于例子中只有VB和c版本的,函数的声明只好自己来。在调用一个函数的时候,总是报“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”异常。这个函数中在他们的例子中是这样声明的:[VB]
Declare Sub LED_SendToScreen Lib "LEDSender.dll" (ByVal dev As Long, ByVal Address As Byte, ByVal Host As String, ByVal Port As Long)[C]
void (_stdcall *LED_SendToScreen)(long dev, BYTE Address, char *Host, WORD port);我在C#中使用了如下的一些声明,都没有成功
public static extern void LED_SendToScreen(int DEV, byte Address, string Host, UInt16 Port);
public static extern void LED_SendToScreen(int DEV, byte Address, StringBuilder Host, UInt16 Port);
public static extern void LED_SendToScreen(int DEV, byte Address, ref string Host, UInt16 Port);
public static extern void LED_SendToScreen(int DEV, byte Address, out string Host, UInt16 Port);
public static extern void LED_SendToScreen(int DEV, byte Address, ref StringBuilder Host, UInt16 Port);
public static extern void LED_SendToScreen(int DEV, byte Address, out StringBuilder Host, UInt16 Port);
public static extern void LED_SendToScreen(int DEV, byte Address, char[] Host, UInt16 Port);
public static extern void LED_SendToScreen(int DEV, byte Address, byte[] Host, UInt16 Port);
public static extern void LED_SendToScreen(int DEV, byte Address, ref char[] Host, UInt16 Port);
public static extern void LED_SendToScreen(int DEV, byte Address, ref byte[] Host, UInt16 Port);
public static extern void LED_SendToScreen(int DEV, byte Address, out char[] Host, UInt16 Port);
public static extern void LED_SendToScreen(int DEV, byte Address, out byte[] Host, UInt16 Port);以上的这些方式我都已经试过了,不知道错误到底在哪。问厂家,厂家的答复是他们的产品没有问题。郁闷中,望高人指点。

解决方案 »

  1.   


    [C] 
    void (_stdcall *LED_SendToScreen)(long dev, BYTE Address, char *Host, WORD port); 
    public static extern void LED_SendToScreen(long DEV, byte Address, StringBuilder Host, UInt16 Port); 
    这个试验下
      

  2.   

    应该不是long的问题。如果c中的声明是long,.net中的声明应该是int32
      

  3.   

    用 ref byte试试看行不行这里有个例子可以看下
    http://topic.csdn.net/u/20070727/15/af8a6093-c0a0-4a31-bba9-f57d8a984223.html
      

  4.   

    IntPtr ptr
    string str = Marshal.PtrToStringAnsi(ptr);
      

  5.   

    能够写的再详细点吗?你的意思是先将string转成IntPtr,调用的时候用IntPtr?
      

  6.   

        
    能够写的再详细点吗?你的意思是先将string转成IntPtr,调用的时候用IntPtr?
      

  7.   

    [VB] 
    Declare Sub LED_SendToScreen Lib "LEDSender.dll" (ByVal dev As Long, ByVal Address As Byte, ByVal Host As String, ByVal Port As Long) [C] 
    void (_stdcall *LED_SendToScreen)(long dev, BYTE Address, char *Host, WORD port); 
    根据2个比较,可以看出vb中第一参数和第4参数都是long,vb中long应该是32位的,那么c中,1、4参数就不合理了,第一个参数32位,第4个是16位,所以vb版本和c版本不同的声明。
    这样看来第2参数基本没有异议,第3参数vb中看应该是知识传入的字符串不传出的,所以应该是string,不过也可以尝试下 Stringbuilder。
    第一参数看起来就应该是C#中的int
    第4参数我认为可以试验下System.UInt16 和System.UInt32 
    另外看C版本,感觉如果那个函数指针有可能是定义在返回值中的,如果是可以尝试如下
    public static extern IntPtr LED_SendToScreen(int DEV, byte Address, string Host, UInt32 Port); 
    不是就尝试下
    public static extern void LED_SendToScreen(int DEV, byte Address, string Host, UInt32 Port); 
      

  8.   

    能够写的再详细点吗?你的意思是先将string转成IntPtr,调用的时候用IntPtr?
      

  9.   

      问题就是厂家给的东西不可靠。手册中的声明是另外一个样子。照你说的改了也不行。我总是怀疑问题出现在第三个参数上string(c里面的类型是char *)
      

  10.   

    肯定有sdk开发文档吧
    我琢磨调用dll最重要是注意参数的类型
      

  11.   

    按照他们的例子,已经用VB实现了LED的控制。可问题是LED的控制只是系统中的一个部分,其他的都是用c#写的。另外LED的生产长提供不了开发库,只能找控制卡的生产者。绕来绕去太麻烦了,工期等不了啊
      

  12.   

    自己搞定了。先用VB生成一个ActiveX控件,用来调用DLL里面的东西,再用C#调用VB生成的ActiveX控件。没有找到问题的真正原因,但是绕过去了。