【发布时间】:2017-12-17 11:26:54
【问题描述】:
我正在触发我的托管代码并启动对非托管代码的调用。非托管代码中有回调。从非托管我在我的托管方法“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);
}
【问题讨论】:
-
一些观察。调用约定可能是错误的。我认为你的代表应该是 cdecl。您可能需要将委托 ref 存储在静态字段中以停止收集它。现在是大的。编组器不知道数组有多长,也无法编组它们。可能需要在属性中指定大小,或者封送为 IntPtr 然后使用 Marshal.Copy。
-
pFTransceive是如何定义的?pf_TxRx必须填充数组还是必须创建一个新数组? -
将 .NET 数组从 C++ 编组到 C# 很复杂(我说的是委托)...非常复杂...您可以尝试
public delegate void fPointer([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] byte[] Sendapdu, ref int Sendlen, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] byte[] Recvapdu, ref int Recvlen);但我不确定它是否会起作用...而且它会很慢(因为缓冲区需要由 .NET 复制) -
@codroipo 我已经更新了 pFTransceive 的定义