110,539
社区成员
发帖
与我相关
我的任务
分享
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace PR202
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("PR202_10Dll.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean OpenSerial(int nPort);
[DllImport("PR202_10Dll.dll", CharSet = CharSet.Ansi, EntryPoint = "RegisterPercCallback", CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean RegisterPercCallback(PercCallback Callback);
[DllImport("PR202_10Dll.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean ReadLastData();
[DllImport("PR202_10Dll.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean CloseSerial();
private void Form1_Load(object sender, EventArgs e)
{
}
public delegate void PercCallback([MarshalAs(UnmanagedType.LPStr)] string pBuffer);
PercCallback callback = new PercCallback(CallBackFunction);
public static void CallBackFunction([MarshalAs(UnmanagedType.LPStr)] string pBuffer)
{
MessageBox.Show(pBuffer); //显示回调内容
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(OpenSerial(3).ToString());//打开串口
RegisterPercCallback(CallBackFunction); //注册C++ DLL 回调
}
private void button3_Click(object sender, EventArgs e)
{
ReadLastData();//读取最后一次的数据:回调数据能显示,但是点击Message.Show的确定后就抛出错误了。
}
private void button5_Click(object sender, EventArgs e)
{
MessageBox.Show(CloseSerial().ToString());
}
}
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(OpenSerial(3).ToString());//打开串口
RegisterPercCallback(CallBackFunction); //注册C++ DLL 回调
}
public partial class Form1 : Form
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void PercCallback(string strResult);//窗体中 delegate,这样可以防止GC立即回收(自己理解的)
public Form1()
{
InitializeComponent();
PercCallback p = new PercCallback(TestCallBack);
RegisterPercCallback(p);
}
方法二:用GCHandle 或KeepAlive。。。此用法没做完。等功力深厚再继续。
非常感谢大家的帮助!谢谢!public delegate void PercCallback([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string strPerc);
报错依旧。。。[/quote]
还有一处需要测试确认:
CallingConvention = CallingConvention.Cdecl 改为 CallingConvention = CallingConvention.StdCall
如果参数出入栈的顺序和方法与约定不同,会导致AccessViolationException[/quote]
StdCall后 在打开端口的时候就报错了,跑不下去:对 PInvoke 函数“PR202!PR202.Form1::RegisterPercCallback”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。”
Cdecl 又报 System.AccessViolationException:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
快奔溃了!!!public delegate void PercCallback([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string strPerc);
报错依旧。。。[/quote]
还有一处需要测试确认:
CallingConvention = CallingConvention.Cdecl 改为 CallingConvention = CallingConvention.StdCall
如果参数出入栈的顺序和方法与约定不同,会导致AccessViolationExceptionpublic delegate void PercCallback([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string strPerc);
报错依旧。。。typedef void (*PercCallback)(const char *strPerc);
//注册回调函数
extern "C" _declspec(dllexport) void RegisterPercCallback(PercCallback Callback);
public delegate void PercCallback(string pBuffer);
public static void CallBackFunction(string str)
{
//MessageBox.Show(str.ToString());
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(OpenSerial(3).ToString());
RegisterPercCallback(CallBackFunction);
}
我打开端口后 注册回调,然后CallBackFunction{}里什么都不写 ReadLastData() 就报错。
我严重怀疑DLL有问题。他们技术又联系不上。好扯。有没有不用委托 可以回调的方法?