簡體   English   中英

從非托管代碼回調到托管代碼

[英]Callback from Unmanaged code to managed

我正在觸發我的托管代碼並啟動對非托管代碼的調用。 非托管代碼中有回調。 從非托管我得到我的托管方法'DelegateMethod'回調。 但我沒有從非托管代碼中獲取正確的參數/參數值。 請在這件事上給予我幫助

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace TestApp
{
    public class Program
    {
        public delegate void fPointer(byte[] Sendapdu, ref int Sendlen, byte[] Recvapdu, ref int Recvlen);

        public struct sCommsAbstraction
        {
            ///Function to send and receive.
            public fPointer pf_TxRx;

            ///Other functions if necessary, e.g. reset
        }

        // Create a method for a delegate. 
        public static void DelegateMethod(byte[] Sendapdu, ref int Sendlen, byte[] Recvapdu, ref int Recvlen)
        {
            //This is called from unmanaged code. I am not getting proper arguments
            Console.WriteLine(Sendlen);
        }

        [DllImport("AuthLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int CmdLib_RegisterItsIO(ref sCommsAbstraction psCommsFunctions);

        [DllImport("AuthLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int CmdLib_OpenApplication();

        [DllImport("TransparentChannel.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int TC_Transceive(byte[] writeBuf, ref int writeBufLen, byte[] readBuf, ref int pwReadBufferLen);

        static void Main(string[] args)
        {
            sCommsAbstraction psCommsFunctions = new sCommsAbstraction();
            // Instantiate the delegate.
            psCommsFunctions.pf_TxRx = DelegateMethod;

            CmdLib_RegisterItsIO(ref psCommsFunctions);
            CmdLib_OpenApplication();
        }
    }
}

我的無限代碼存在於此處 - CmdLib.c

//C code - unmanaged

typedef int32_t (*pFTransceive)(const uint8_t *prgbWriteBuffer, const uint16_t *pwWriteBufferLen, uint8_t *prgbReadBuffer, uint16_t *pwReadBufferLen);

typedef struct sCommsAbstraction
{
    ///Function to send and receive.
    pFTransceive pf_TxRx;

    ///Other functions if necessary, e.g. reset
}sCommsAbstraction_d

static sCommsAbstraction_d sCommsAbstraction = {0};

void CmdLib_RegisterItsIO(const sCommsAbstraction_d *psCommsFunctions)
{
    sCommsAbstraction.pf_TxRx = psCommsFunctions->pf_TxRx;    
}
void CmdLib_OpenApplication()
{
    sCommsAbstraction.pf_TxRx(rgbAPDUBuffer,&wTotalLength,rgbAPDUBuffer,&psApduData->wResponseLength);
}

您的委托聲明與pFTransceive函數指針聲明不匹配。 這會在回調方法中生成垃圾參數值。

靠近:

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void fPointer(
        [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
        byte[] Sendapdu, ref short Sendlen,
        [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]
        byte[] Recvapdu, ref short Recvlen
    );

請注意必需的屬性以匹配C / C ++程序中使用的默認調用約定。 短的參數類型匹配uint16_t .`

更多關於在這篇文章中調用約定的奧秘。


    sCommsAbstraction psCommsFunctions = new sCommsAbstraction();

這是你必須擔心的另一件事。 只要本機代碼可以進行回調,該對象就需要存活。 現在它沒有,下一個垃圾收集將破壞它,因為垃圾收集器無法找出本機代碼正在使用它。 當本機代碼進行回調時Kaboom。 你還沒有看到那個bug,調試器現在讓對象保持活着狀態。 這不會發生在生產中。

如上所述,您需要將此語句添加到Main()方法的底部:

    GC.KeepAlive(psCommsFunctions);

將它存儲在靜態變量中是更好的方法,只有在您知道本機代碼不再進行回調的事實時才將其設置為null

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM