最近完成了一个C++版本的对外sdk程序,其中有部分回调函数使用。

C++程序使用时没有异常,但是在C#环境下使用时出了点问题,简单总结下。

感谢博客:http://blog.csdn.net/songjinshi/article/details/8153635 帮助我解决了问题。

C++中的回调函数原型如下:

typedef void (STDCALL *fCallback)(const char* csDetail, void *pUser);

其中有一个参数是char * ,就是字符指针,这里需要特别注意。

在C#中需要以委托完成相应回调操作,心路历程如下:

1,开始使用如下形式的委托函数:

public delegate void MSGCALLBACK(ref byte pBuffer, UIntPtr pUser);

出现问题,回调函数仅能接收到一个字符,而非整个字符数组的值。

2,使用如下形式的委托函数:

public delegate void MSGCALLBACK(ref byte[] pBuffer, UIntPtr pUser);

出现如1 的问题,回调函数仅能接收到一个字符,而非整个字符数组的值。

3,使用string代替byte数组,委托函数如下:

public delegate void MSGCALLBACK(string pBuffer, UIntPtr pUser);

正常情况下接收数据均正常,但是在接收中文字符“面”是,出现异常,查看内存整个内存地址位置的值都异常了,如下:

相应内存地址内容如下:

这里具体什么原因确实没有找到,希望有大神可以帮忙解答。

4,最终正确的委托函数如下:

需要包含包  “using System.Runtime.InteropServices;

public delegate void MSGCALLBACK([MarshalAs(UnmanagedType.LPArray, SizeConst = 8000)]byte[] pBuffer, UIntPtr pUser);

成功的接收回调消息并完成消息解析,没有出现任何异常。

解释如下:

在给c++传入数组参数时,必须得用 [MarshalAs(UnmanagedType.LPArray,SizeConst=8000)] 处理一下,相当于是告诉c++,c#传入的是一个长度为8000的数组类型,如果不写这句话的话,你回调函数接收到的参数将只有一条数据。

对于MarshalAs,MarshalAs属性指示如何在托管代码和非托管代码之间封送数据。

当 MarshalAsAttribute.Value 设置为 LPArray时,必须设置 SizeConst 以指示数组中的元素数。当需要区分字符串类型时,ArraySubType 字段可以选择包含数组元素的 UnmanagedType。此 UnmanagedType 只可用于作为结构中的字段的数组。而SizeConst则是指数组中的元素个数。

转载一个链接,用以帮助理解MarshalAs如何使用:

http://blog.csdn.net/xiaobai1593/article/details/7025775

c#调用c++带有回调函数方法的实现的更多相关文章

  1. Unity C# 调用 C++ DLL 并在 DLL 中调用 C# 的回调函数

    Unity C# 调用 C++ DLL 并在 DLL 中调用 C# 的回调函数~~~    呵呵... 看着有点晕.. 再解释一下就是 在Unity中 使用 C# 调用 C++ 写的 DLL, 但是在 ...

  2. Python并发编程06 /阻塞、异步调用/同步调用、异步回调函数、线程queue、事件event、协程

    Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件event.协程 目录 Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件 ...

  3. 基于委托的C#异步编程的一个小例子 带有回调函数的例子

    我创建的是一个winform测试项目:界面如下: 设置: 下面是代码: using System; using System.Collections.Generic; using System.Com ...

  4. 浅尝辄止——在C++中调用C#的回调函数——COM方式

    这种方式比较简单,给大家分享一下,同时讲一下SafeArray内定义结构体的方法 1. 需求描述 需求是这样的,C++代码和C#代码相互通信(C++一般做服务,C#做客户端),C++一侧准备好数据,然 ...

  5. 微信小程序如何把接口调用成功的回调函数返回的参数return出去?(promise就可以解决)

    举个栗子//获取应用实例 //const app = getApp() //const util = require('../../utils/util.js') //const sign = uti ...

  6. wx: wx.showModal 回调函数中调用自定义方法

    一.在回调函数中调用自定义方法: 回调函数中不能直接使用this,需要在外面定义 var that = this 然后 that.自定义的方法.如下: //删除 onDelete: function ...

  7. [转]理解与使用Javascript中的回调函数

    在Javascript中,函数是第一类对象,这意味着函数可以像对象一样按照第一类管理被使用.既然函数实际上是对象:它们能被“存储”在变量中,能作为函数参数被传递,能在函数中被创建,能从函数中返回. 因 ...

  8. 【JavaScript】理解与使用Javascript中的回调函数

    在Javascript中,函数是第一类对象,这意味着函数可以像对象一样按照第一类管理被使用.既然函数实际上是对象:它们能被“存储”在变量中,能作为函数参数被传递,能在函数中被创建,能从函数中返回. 因 ...

  9. Delphi回调函数及其使用

    Delphi回调函数及其使用 1 回调函数的概述 回调函数是这样一种机制:调用者在初始化一个对象(这里的对象是泛指,包括OOP中的对象.全局函数等)时,将一些参数传递给对象,同时将一个调用者可以访问的 ...

随机推荐

  1. Oracle 数字操作。数字函数。mod(),trunc(),round(),ceil(),floor的使用

    1,取整函数(ceil 向上取整,floor 向下取整) 第一种方式: ) from dual -- 取整 trunc (1.9) = 1 第二种方式 select ceil(66.6) N1,flo ...

  2. iBatis 使用总结

    http://blog.csdn.net/caihaijiang/article/details/6438633 --日期格式化 date_format(createtime,'%Y-%m-%d') ...

  3. 【Scala】使用Option、Some、None,避免使用null

    避免null使用 大多数语言都有一个特殊的关键字或者对象来表示一个对象引用的是"无",在Java,它是null.在Java 里,null 是一个关键字,不是一个对象,所以对它调用不 ...

  4. Mybatis(三):MyBatis缓存详解

    MyBatis缓存分为一级缓存和二级缓存 一级缓存 MyBatis的一级缓存指的是在一个Session域内,session为关闭的时候执行的查询会根据SQL为key被缓存(跟mysql缓存一样,修改任 ...

  5. Mysql又一次整理笔记--woods备忘

    ==============================SQL备忘 CRUD 查询 多表 事件等=============================== ------------------ ...

  6. Creating Dialogbased Windows Application (4) / 创建基于对话框的Windows应用程序(四)Edit Control、Combo Box的应用、Unicode转ANSI、Open File Dialog、文件读取、可变参数、文本框自动滚动 / VC++, Windows

    创建基于对话框的Windows应用程序(四)—— Edit Control.Combo Box的应用.Unicode转ANSI.Open File Dialog.文件读取.可变参数.自动滚动 之前的介 ...

  7. 设置一个label显示多种颜色,多种字体大小

    UILabel* label = [[UILabel alloc] init]; label.frame = CGRectMake(0, 100, 200, 100); label.textColor ...

  8. java 服务接口API限流 Rate Limit

    一.场景描述 很多做服务接口的人或多或少的遇到这样的场景,由于业务应用系统的负载能力有限,为了防止非预期的请求对系统压力过大而拖垮业务应用系统. 也就是面对大流量时,如何进行流量控制? 服务接口的流量 ...

  9. Android.mk解析

    https://developer.android.com/ndk/guides/android_mk.html#over LOCAL_STATIC_LIBRARIES PREBUILT_STATIC ...

  10. Linux Linux程序练习四

    编写两个不同的可执行程序,名称分别为a和b,b为a的子进程. 在a程序中调用open函数打开a.txt文件. 在b程序不可以调用open或者fopen,只允许调用read函数来实现读取a.txt文件. ...