首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从非托管代码回调到托管代码

从非托管代码回调到托管代码
EN

Stack Overflow用户
提问于 2015-07-20 08:35:33
回答 1查看 1.1K关注 0票数 4

我正在触发托管代码并发起对非托管代码的调用。在非托管代码中有一个回调。在非托管中,我在我的托管方法'DelegateMethod‘中得到回调。但是,我没有从非托管代码中获得适当的参数/参数值。请帮我处理这个

代码语言:javascript
复制
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

代码语言:javascript
复制
//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);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-20 10:54:34

您的委托声明与pFTransceive函数指针声明不匹配。它在回调方法中生成垃圾参数值。

靠近:

代码语言:javascript
复制
    [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.`的短参数类型。

更多关于在this post中调用约定的奥秘。

代码语言:javascript
复制
    sCommsAbstraction psCommsFunctions = new sCommsAbstraction();

这是你不得不担心的另一件事。只要本机代码能够进行回调,该对象就需要生存。现在它没有,下一个垃圾收集将销毁它,因为垃圾收集器无法找到本机代码正在使用它。当本机代码进行回调时,Kaboom。您还没有看到该bug,调试器现在使对象保持活动状态。这在生产中是不会发生的。

如前所述,您需要将此语句添加到Main()方法的底部:

代码语言:javascript
复制
    GC.KeepAlive(psCommsFunctions);

将其存储在静态变量中是更好的方法,只有当您知道本机代码将不再进行回调时,才会将其设置为null

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31511996

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档