lionk_ii 2013-11-06 08:13 采纳率: 0%
浏览 2677

C#调用C DLL(char *传出参数)时,报错参数不匹配

public class LLht
{

    //手持机下载上传
    [DllImport("llht.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    public static extern int llht_down(string PCFile, string HTFile, int port, int baud, int SerialNO);

    [DllImport("llht.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    public static extern int llht_up(string PCFile, string HTFile, int iPort, int iBaud, int iSerialNo);

    //取得HT 的文件放在FILEBUFF 中 每个文件的长度不超过12字节,返回是文件的数目  
    [DllImport("ht32dll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    public static extern long GetHtFile(ref byte filebuff, uint iPort, long iBaud);    
}

这就是DLL的入口函数,没有DLL的头文件,注释也只有那一行,long GetHtFile(char * filebuff, unsigned int iPort, long iBaud);这是函数原型。
调用代码如下:

        string name = "000000000000";
        byte[] filename = new byte[12];
        for (int i = 0; i < name.Length; i++)
        {
            filename[i] = (byte)name[i];
        }
        long read = LLht.GetHtFile(ref filename[0], comid, 57600);//此行报错
        MessageBox.Show(read + ":" + filename[0].ToString());

报错内容为:对 PInvoke 函数“数据审核!数据审核.LLht::GetHtFile”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。

求助各位大神

  • 写回答

1条回答

  • ChatGPTᴼᴾᴱᴺᴬᴵ 2023-02-27 20:05
    关注

    该回答引用ChatGPT

    根据你提供的代码和报错信息,可以看出问题是出现在GetHtFile函数上,因为这个函数使用了ref byte类型的参数filebuff,而原始DLL中的函数签名使用了char*类型的参数。这两种类型在内存中的表示方式是不同的,因此调用这个函数时会发生错误。


    为了解决这个问题,你可以将GetHtFile函数的参数类型改为IntPtr,然后在调用该函数时将filename数组的首地址作为参数传递。这样可以确保传递给非托管代码的是正确的指针类型,并且不会发生内存对齐的问题。


    修改后的代码如下:

    [DllImport("ht32dll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    public static extern long GetHtFile(IntPtr filebuff, uint iPort, long iBaud);
    
    ...
    
    byte[] filename = Encoding.ASCII.GetBytes("000000000000");
    IntPtr filebuff = Marshal.AllocHGlobal(filename.Length);
    Marshal.Copy(filename, 0, filebuff, filename.Length);
    
    long read = LLht.GetHtFile(filebuff, comid, 57600);
    
    Marshal.Copy(filebuff, filename, 0, filename.Length);
    Marshal.FreeHGlobal(filebuff);
    

    在这个示例中,我们使用Marshal.AllocHGlobal函数分配了一块非托管内存,然后使用Marshal.Copy函数将filename数组的数据复制到这个内存中。然后我们将filebuff作为参数传递给GetHtFile函数,函数将读取这块内存中的数据并返回。最后我们再次使用Marshal.Copy函数将内存中的数据复制回filename数组,并使用Marshal.FreeHGlobal函数释放内存。

    评论

报告相同问题?

悬赏问题

  • ¥20 iqoo11 如何下载安装工程模式
  • ¥15 本题的答案是不是有问题
  • ¥15 关于#r语言#的问题:(svydesign)为什么在一个大的数据集中抽取了一个小数据集
  • ¥15 C++使用Gunplot
  • ¥15 这个电路是如何实现路灯控制器的,原理是什么,怎么求解灯亮起后熄灭的时间如图?
  • ¥15 matlab数字图像处理频率域滤波
  • ¥15 在abaqus做了二维正交切削模型,给刀具添加了超声振动条件后输出切削力为什么比普通切削增大这么多
  • ¥15 ELGamal和paillier计算效率谁快?
  • ¥15 蓝桥杯单片机第十三届第一场,整点继电器吸合,5s后断开出现了问题
  • ¥15 file converter 转换格式失败 报错 Error marking filters as finished,如何解决?