现在有个硬件的DLL,我们需要通过DLL控制硬件设备,需要用到DLL的2个函数,这2个函数原型是这样的JS_OK 对应值 1,
JS_COMM_ERR 对应值-3,
JS_TYPE_ERR对应值-10。HANDLE PASCAL OpenCommPort(LPCSTR lpszPortNum,DWORD dwBaudRate)
lpszPortNum 为串行端口,dwBaudRate为端口通讯速率。函数正确运行返回端口句柄。LONG PASCAL OpenDoor(HANDLE hCom,BYTE Devno,BYTE CtrNo)
hCom为端口句柄,Devno 设备号,CtrNo为控制类型,默认0。函数调用成功返回JS_OK,不成功返回JS_COMM_ERR或者JS_TYPE_ERR。我不熟悉PASCAL,关于数据类型的对应声明估计出现了问题,我在C#中这样调用
[DllImport(@"D:\招投标中心项目\201Comm.dll", EntryPoint = "OpenCommPort", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]public static extern long OpenCommPort(string num, int intBaudRate);[DllImport(@"D:\招投标中心项目\201Comm.dll", EntryPoint = "OpenDoor", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]public static extern int OpenDoor(ref long Handle,int Devno, int CtrNo);程序中调用的地方这样调用
long a = OpenCommPort("COM1", 9600);
int b = OpenDoor(ref a,0, 1);
现在测试a值可以正确返回端口句柄号
b的值总是-3,不知道是否是参数类型设置错误,请大家帮忙看下。

解决方案 »

  1.   

    public static extern IntPtr OpenCommPort(string num, unsigned long ulBaudRate);
    public static extern int OpenDoor(IntPtr Handle,byte Devno, byte CtrNo);
      

  2.   

    [DllImportAttribute(@"D:\招投标中心项目\201Comm.dll", EntryPoint="OpenCommPort", CallingConvention=CallingConvention.StdCall)]
    public static extern  IntPtr OpenCommPort([InAttribute()] [MarshalAsAttribute(UnmanagedType.LPStr)] string lpszPortNum, uint dwBaudRate) ;
    [DllImportAttribute(@"D:\招投标中心项目\201Comm.dll", EntryPoint="OpenDoor", CallingConvention=CallingConvention.StdCall)]
    public static extern  int OpenDoor(IntPtr hCom, byte Devno, byte CtrNo) ;
    试下吧,不知道好不好.
      

  3.   

    TO flyerwing:
    非常感谢,请问能解释下这个的意思么, [InAttribute()] [MarshalAsAttribute(UnmanagedType.LPStr)] 
    同时LPDWORD又应该对应什么的类型呢?
      

  4.   

    传入长字符串指针,不知道对不对.
    LPDWORD [InAttribute(),OutAttribute()]ref uint LPDWORD
    这个估计得视情况而看吧.
      

  5.   

    InAttribute,帮助中的解释为:
    指示应将数据从调用方封送到被调用方,而不返回到调用方。
    InAttribute 是可选项。只有 COM Interop 和平台调用才支持此属性。如果缺少显式设置,Interop 封送拆收器将根据参数类型来假定规则,不论参数是通过引用传递还是通过值传递,也不论类型是可直接复制到本机结构中,还是不能直接复制到本机结构中。例如,始终假定 StringBuilder 类为 In/Out,并假定通过值传递的字符串数组为 In。LPDWORD,为DWORD指针,C#可以使用ref uint试试
      

  6.   

    谢谢楼上2位,现在项目比较急,具体的下来看书学习,OPenDOOR已经可以实现。门已经可以打开,现在急需要用其中一个函数AddList()
    函数原型如下
    LONG PASCAL AddList(HANDLE hCom,BYTE DevNo,DWORD CardSN,LPCSTR pName,LPCSTR pNo,LPCSTR pPIN,LPCSTR pLimitTime,BYTE Door1App,BYTE Door2App)数据取值说明
    pName持卡人姓名字符串超过8 个字符(4 个汉字),之后的将被截除,
    pNo 持卡人工号字符串超过11 个字符,之后的将被截除,
    pPIN 持卡人个人密码最多6 位数字(0——9),
    组成pLimitTime 卡片有效期字符串格式如下:
    年(2)+月(2)+日(2),十六进制表示
    如:“030911”表示2003 年9 月17 日 
    Door1App 门1 的应用群组号有效取值范围(0——15)其余值均无效;可以用写入无效值,禁止卡片在此扇门的权限。
    Door2App 门2 的应用群组号,同上我申明的语句:
    [DllImport(@"D:\招投标中心项目\a08.dll", EntryPoint = "OpenCommPort", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]public static extern IntPtr OpenCommPort([InAttribute()] [MarshalAsAttribute(UnmanagedType.LPStr)] string lpszPortNum, uint dwBaudRate);[DllImport(@"D:\招投标中心项目\a08.dll", EntryPoint = "AddList", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]public static extern int AddList(IntPtr Handle, byte Devno, uint CardSn, string strName, string strNo, string strPass, string strLimitTime, byte Door1App, byte Door2App);
    测试调用的时候
    IntPtr a = OpenCommPort("COM1", 9600);
    int b = AddList(a, 0, 9637114, "aaa", "000009", "222222", "030901", 0, 0);
    执行后b的值总是返回说输入字符串长度不匹配,排除函数说明本身的错误外,请帮我坚持下是否函数申明和调用的哪个地方有问题呢?谢谢了!       
      

  7.   

    上边的问题解决了,申明参数时没有加上这个[MarshalAsAttribute(UnmanagedType.LPStr)] 
    现在还有个问题,就是对于像这样有输出参数的在C#中怎么申明
    LONG PASCAL ReadCardSN(HANDLE hCom,BYTE Dno,LPDWORD pCardSn)
      

  8.   

    LPDWORD pCardSn应该是一个无符号32位整数的指针
    会在其中写上卡号什么的吧,用ref uint试试
      

  9.   

    我是这样写的,但是老是提升通讯失败
    public static extern int ReadCardSN(IntPtr Handle, byte Devno, [InAttribute(), OutAttribute()] ref uint CardSn);
    同时还想请教一下,我自己的程序如何知道有人在读卡器上刷卡了呢,就是如何类似银行卡卡插进去后程序就会知道,并且做出处理。
      

  10.   

    现在关键是我的这个函数的申明不知道是否正确
    public static extern int ReadCardSN(IntPtr Handle, byte Devno, [InAttribute(), OutAttribute()] ref uint CardSn);
      

  11.   


    卖硬件的厂商应该提供一个事件的,或者回调函数啥的
    在厂商给的Dll中找找有没有CallBack字样的东西
      

  12.   


    参数是否正确,楼主完全可以用VC写一个Dll测试一下,我都不知道这样试过多少回了,好多麻烦的修饰[InAttribute(), OutAttribute()]之类的根本不需要
      

  13.   

    CALLBACK是没有了,我看到有个READSTATE函数,他有个伪代码,通过一个死循环不断的检测这个函数,如果有人刷卡这个函数就会返回相应的值。现在着急的就是这个函数里LPDWORD 类型的参数在C#中该如何申明和使用,才能正确传进去后得到值。
      

  14.   

    帮你试一下LPDWORD,先弄个Dll://用VC2008编译(选择编译为C语言)
    __declspec(dllexport) void ReadCard(LPDWORD pd)
    {
    DWORD dw = 345;
    memcpy(pd, &dw, sizeof(DWORD));
    }弄个.Net的控制台程序测试:class Program
        {
            [DllImport("Card.dll")]//导入Dll中的函数
            static extern void ReadCard(ref uint dw);        static void Main(string[] args)
            {
                uint dw = 0;
                ReadCard(ref dw);
                Console.WriteLine(dw);//输出345,调用正确
            }
        }猜一下:
    LONG ReadCardSN(HANDLE hCom,BYTE Devno,LPDWORD pCardSn)
    第二个参数应该是设备号
    第三个参数应该是卡号,一个无符号32位整数的指针,读取的卡号要写到它指向的对象
      

  15.   


    应该看下DEMO中ReadCardSN是如何调用的,对于pCardSn参数是如何处理的
      

  16.   

    关键是这个该死的没有DEMO,只有一个简单的函数说明。ReadCardSN这个函数偶尔几次能调用成功,但是调用成功后门禁的控制器就好像死机了一样,里边的数据再也读不出了,只有初始化后才能使用,也不知道这又是什么原因。有做过门禁软件的么。
      

  17.   

    楼主你好,这几天老板也吹着 要搞门禁,看老下你发的 内容, 
    我好像遇到了 和你同一个 门禁的接口 调用问题
    我手里的 DLL版本是delphi的 ,
    不过 我没有相关的demo,
    该死的提供商 理直气壮的向我吼道:“现在盗版那么多,我们怎么会提供二次开发文档,你说的那个是7,8年前的事情了”
    楼主大人要是看到的话 ,能发下demo给我看看么? 我的email是 [email protected]