Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从非托管代码回调到托管代码_C#_Pinvoke - Fatal编程技术网

C# 从非托管代码回调到托管代码

C# 从非托管代码回调到托管代码,c#,pinvoke,C#,Pinvoke,我正在触发托管代码并启动对非托管代码的调用。非托管代码中存在回调。从非托管中,我在托管方法“DelegateMethod”中获得回调。但我没有从非托管代码中获得正确的参数/参数值。请帮我做这个 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace TestApp { publ

我正在触发托管代码并启动对非托管代码的调用。非托管代码中存在回调。从非托管中,我在托管方法“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\u t
`

更多关于召集会议的秘密


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

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


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

一些观察结果。呼叫约定可能是错误的。我认为你的代表应该是cdecl。您可能需要将委托引用存储在静态字段中,以停止对其进行收集。现在是大的。封送处理程序不知道数组的长度,因此无法封送它们。可能需要在属性中指定大小,或者封送为IntPtr,然后使用marshal.Copy。如何定义
pFTransceive
<代码> PFY-TXRX必须填充数组,还是必须创建一个新的数组?封送处理。从C++到C.NET的Net数组是复杂的(我在说委托)…非常复杂。。。您可以尝试
public delegate void fPointer([Marshallas(UnmanagedType.LPArray,SizeParamIndex=1)]字节[]Sendapdu,ref int Sendlen,[Marshallas(UnmanagedType.LPArray,SizeParamIndex=3)]字节[]Recvapdu,ref int Recvlen)但我不确定它是否有效。。。而且速度会很慢(因为缓冲区需要被.NET复制)@codroipo我已经更新了pFTransceiveVery的定义很好的解释@Hans,谢谢allot:)封送器如何在不知道数组长度的情况下封送数组?
    sCommsAbstraction psCommsFunctions = new sCommsAbstraction();
    GC.KeepAlive(psCommsFunctions);