首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

小弟我用C#调用一个C++的DLL,出现异常,请帮忙解决,明天下班给分

2013-01-23 
我用C#调用一个C++的DLL,出现错误,请帮忙解决,明天上班给分首先看一下DLL的说明文档:RdrReader433A.dll1、

我用C#调用一个C++的DLL,出现错误,请帮忙解决,明天上班给分
首先看一下DLL的说明文档:RdrReader433A.dll
1、打开串口:int RdrOpenPort(char *port)
2、关闭串口:int RdrClosePort(char *port)
3、获得卡号报文:int RdrGetCardId(char *port, char *outcardid)

我只是做一个DEMO来看看效果。可是报错。
我在添加引用DLL的时候报错:未能添加对“.DLL”的引用。请确保此文件可访问并且是一个有效的程序集或COM组件。
于是我换另一种方法来引用此DLL。
首先我做了一个桌面程序,别的没有,只有一个按钮和一个文本框。下边是我的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        [DllImport("RdrReader433A.dll", EntryPoint = "RdrOpenPort")]
        public static extern int RdrOpenSerialPort433(string port);
        [DllImport("RdrReader433A.dll", EntryPoint = "RdrGetCardId", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

        //public static extern int RdrGetCardidBy433(string port, char* recvdata);
        public static extern int RdrGetCardidBy433(string port,out StringBuilder recvdata);
        [DllImport("RdrReader433A.dll", EntryPoint = "RdrClosePort")]
        public static extern int RdrCloseSerialPort433(string port);
        //[MarshalAs(UnmanagedType.LPArray)]
        //public byte[] str = new byte[1024];


        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                this.textBox1.Text = RdrOpenSerialPort433("COM1").ToString();
                textBox1.Text += "|";
                StringBuilder str;

                this.textBox1.Text += RdrGetCardidBy433("COM1", out str).ToString();
                textBox1.Text += "|";
                this.textBox1.Text += str.ToString();
                textBox1.Text += "|";
                this.textBox1.Text += RdrCloseSerialPort433("COM1").ToString();
            }


            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                //throw;
            }
            
            
        }
    }
}

编译没有错误,但是运行的时候,运行到:
this.textBox1.Text += RdrGetCardidBy433("COM1",out str).ToString();
这行的时候报错,错误提示是:尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
c# c++ dll
[解决办法]
StringBuilder不要加out
[解决办法]
StringBuilder要先初始化,并且容量必须足够大
[解决办法]
你将out去掉了吗?
应该这样写

public static extern int RdrGetCardidBy433(String port,StringBuilder recvdata);

然后调用
StringBuilder str = new StringBuilder(1024);
RdrGetCardidBy433("COM1", str);
textBox1.Text = str.ToString();

这样子应该就不会错了。
[解决办法]
感觉应该是访问函数访问对象越界了
[解决办法]
如果初始化了string后的话 添加out应该是没有错的把
[解决办法]
StringBuilder 是.net的类,你传给c++,
它怎么知道StringBuilder是个什么东东!
跟c++通讯时,尽量用byte数组或int,string这类的东西最好不要用.
out byte[] 试试
[解决办法]
StringBuilder 应该做不了out参数,换成string试试
[解决办法]
一般都把char*封装成stringbuilder,也不需要out吧 
[解决办法]
存在疑问的朋友,可以参考一下MSDN给出的示例:


例如,Microsoft Win32 API GetWindowText 函数(在 Windows.h 中定义的)是必须传递到非托管代码中进行操作的定长字符缓冲区。LpString 指向大小为 nMaxCount 的由调用方分配的缓冲区。调用方应分配缓冲区,并将 nMaxCount 参数设置为所分配的缓冲区的大小。以下代码显示 Windows.h 中定义的 GetWindowText 函数声明。


int GetWindowText(
HWND hWnd,        // Handle to window or control.
LPTStr lpString,  // Text buffer.
int nMaxCount     // Maximum number of characters to copy.
);

 

StringBuilder 可以由被调用方取消引用和修改,条件是它不超过 StringBuilder 的容量。下面的代码示例说明可以如何将 StringBuilder 初始化为固定长度。


public class Win32API {
[DllImport("User32.Dll")]
public static extern void GetWindowText(int h, StringBuilder s, 
int nMaxCount);
}
public class Window {
   internal int h;        // Internal handle to Window.
   public String GetText() {


      StringBuilder sb = new StringBuilder(256);
      Win32API.GetWindowText(h, sb, sb.Capacity + 1);
   return sb.ToString();
   }
}


 

热点排行