六月 11, 2015

从C++的dll中Callback到C#返回数组:只取到了第一个元素

Written by

假设C/C++的dll中定义回调函数:

// Received data callback
typedef void(__stdcall *ReceivedDataCallback)(SerialPortRef sp, unsigned char* data, int len);


/*********************************************************
* Library API definitions *
/*********************************************************/
#ifdef __cplusplus
extern "C" {
#endif

 // Register handl to receive data from a SerialPort.
 SERIALPORTRW_API void RegisterReceivedDataCallback(SerialPortRef sp, ReceivedDataCallback handle);

//......................

C#中包含dll,通过包装dll的函数和回调函数,以便dll中收到数据时回调到C#:

// Wrapper of library by C#
namespace PluginImport
{
	#region delegates
    public delegate void ReceivedDataCallback(IntPtr serialPortRef, [MarshalAs(UnmanagedType.LPArray)]byte[] data, int len);
	#endregion
		
	#region API Wraper
	public class SerialPortDevice
	{
		// Register handl to receive data from a SerialPort.
		[DllImport("SerialPortDevice", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern void RegisterReceivedDataCallback(UIntPtr sp, ReceivedDataCallback handle);

使用此DLL包装的API:

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            ReceivedDataCallback = (IntPtr serialPortRef, byte[] data, int len) =>
            {
                byte[] localData = data;

                this.Dispatcher.Invoke(new Action(() => { tbLog.Text += ByteUtils.bytesToHexString(localData, 0, len); }));
            };

            SerialPortStatusChanged = (IntPtr serialPortRef, SerialPortStatus status, string msg) =>
            {
                this.Dispatcher.Invoke(new Action(() => { tbLog.Text += "\r\n" + msg; }));
            };


            spRef = SerialPortDevice.CreateSerialPort();
            if (spRef != UIntPtr.Zero)
            {
                SerialPortDevice.RegisterReceivedDataCallback(spRef, ReceivedDataCallback);
                SerialPortDevice.RegisterSerialPortStatusChangedCallback(spRef, SerialPortStatusChanged);
            }

发现上面红色部分的data的长度总是一个字节。

原因:

marshaller不知道data的长度到底是多少,只是简单的按照数据类型返回了数组中的第一个元素,根本没有办法marshal。

正确的做法是将data定义为指针,然后通过拷贝的方法将数据取到C#端:

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            ReceivedDataCallback = (IntPtr serialPortRef, IntPtr data, int len) =>
            {
                byte[] localData = new byte[len];
                Marshal.Copy(data, localData, 0, len);
                
                string strHex = ByteUtils.bytesToHexString(localData, 0, len);

                this.Dispatcher.Invoke(new Action(() => { tbLog.Text += "\r\n" + strHex; }));
            };

            SerialPortStatusChanged = (IntPtr serialPortRef, SerialPortStatus status, string msg) =>
            {
                this.Dispatcher.Invoke(new Action(() => { tbLog.Text += "\r\n" + msg; }));
            };


            spRef = SerialPortDevice.CreateSerialPort();
            if (spRef != UIntPtr.Zero)
            {
                SerialPortDevice.RegisterReceivedDataCallback(spRef, ReceivedDataCallback);
                SerialPortDevice.RegisterSerialPortStatusChangedCallback(spRef, SerialPortStatusChanged);
            }
        }

当然,在这之前要在C#端的回调函数定义中的数据也要改成指针:

public delegate void ReceivedDataCallback(IntPtr serialPortRef, IntPtr data, int len);

 

Category : 其他

Tags :

Comments

10 Responses

  1. Moon说道:

    Inoomratifn is power and now I’m a !@#$ing dictator.

  2. You did the a awesome work writing and revealing the hidden beneficial functions of BlogEngine.Net, that I found it was popularly used by bloggers nowadays. I think BE has emerged to be one among the top blogging platform best now. I wish you great luck with your blogging experiences.

  3. Hypocrisy is not a very becoming trait, YouTube!! You protect accounts that are known to violate your Terms of Use and eliminate those who abide by it. Do I have to mention names? (no, we all know who I am talking about). Fix this problem or maybe the media/press will appreciate your sweat.

  4. HOLA! ESPERANZA! SOY ALESS MARTIN VILLACASTIN Y HE RECIEN LLEAGDO A TU PAGINA EN LA CUAL DESEO DEJAR MIS FELICITACIONES IMPRESAS. ME ALEGRO DE TUS LOGROS PERSONALES Y TU RICA CULTURA SIN OLVIDAR TU GRAN CORAZÓN HACIA LOS DEMAS. RECIBE UN MUY CORDIAL SALUDO ESPECIALMENTE DEL PARENTESCO QUE NOS UNE. UN ABRAZO, ESPE!!!FDO.: Aless Matin Villacastin…………………………………………

  5. That looks like an awesome way to start the year off Layla! I’m glad to hear that the new shoes are working out well for you. And 141.7 miles in a month is some seriously nice mileage, way to go!

  6. Carter, what’s that you’re saying? People are using the internet? Who, who are these people??? I want to know now!Joking aside, it is too bad they’re behing. They haven’t grasped the magnitude early enough, but better late than never – right?

  7. http://www./说道:

    There are plenty of union members who understand the situation and why their numbers are declning but are afraid to speak out. Retired members can speak out.

  8. http://www./说道:

    I absolutely love how it turned out in your fabric. I just ordered some of the blue and red! Thank you so much to Jess and Grandma G for reviewing my pattern! I'm so happy that you liked it!

  9. There seems to be sympathy for the killer among some people on this site. Why would that be an assumption. The post was not about the guilt or innocence of Richard, it was about the Judge's behavior.It seems there is little understanding of the law when people had to go to look up how bad the guy was. Was this to see if he deserved justice?

  10. fut 14说道:

    I appreciate you taking to time to contribute That’s very helpful.

发表评论

电子邮件地址不会被公开。

Proudly powered by WordPress and Sweet Tech Theme