C#调用C++DLL回调函数的问题
为调度台程序,该回调函数监视分机状态改变并获取状态值,在C++的demo里,可以即时得到状态值,而在C#中,能够得到分机状态,然而状态改变时却不能及时得到正确的数据,是怎...
为调度台程序,该回调函数监视分机状态改变并获取状态值,在C++的demo里,可以即时得到状态值,而在C#中,能够得到分机状态,然而状态改变时却不能及时得到正确的数据,是怎么回事,是dll的问题还是C#代码有问题.求解
C++:
typedef void (__stdcall *StateCb)(char*name, char*ip, char*state ,void* pThis);
DISPATCH_API void BT_DISPATCH_SetStateCallBack(StateCb stateCb, void*pThis);
C#:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]--有没有这个效果一样
public delegate void PeerState(string name, string ip, string state, IntPtr pThis);
[DllImport("dispatch.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void BT_DISPATCH_SetStateCallBack(PeerState peerstate,IntPtr pThis);
不知道哪里有问题... 展开
C++:
typedef void (__stdcall *StateCb)(char*name, char*ip, char*state ,void* pThis);
DISPATCH_API void BT_DISPATCH_SetStateCallBack(StateCb stateCb, void*pThis);
C#:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]--有没有这个效果一样
public delegate void PeerState(string name, string ip, string state, IntPtr pThis);
[DllImport("dispatch.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void BT_DISPATCH_SetStateCallBack(PeerState peerstate,IntPtr pThis);
不知道哪里有问题... 展开
1个回答
展开全部
关键是 lpOnRecvCardEvent 这个函数的第二个参数是个 C++ 指针。
楼主在 C# 中声明这个导出函数时,使用了并不对应的 CardEvent[] C# 数组类型。
正确的做法是: 在 C# 声明 lpOnRecvCardEvent 时,第二个参数应该是 IntPtr ,不是数组。
由于楼主的这个 VC DLL 可能是自己写的,我没办法给出正确代码。
我提供一份模拟代码做参考:
----------------------------------------------------------------------------------------------------
VC DLL:
StructMod.h
#pragma once
#include <Windows.h>
#ifndef STRUCTMOD_EXPORT
#define STRUCTMOD_EXPORT extern "C" __declspec(dllimport)
#endif
typedef struct _tagCardEvent {
DWORD CardNo;
INT32 EvtYear;
} CardEvent, *PCardEvent;
STRUCTMOD_EXPORT CardEvent;
STRUCTMOD_EXPORT PCardEvent;
typedef void CALLBACK PFNTEST(PCardEvent pce, INT32 nEvt);
STRUCTMOD_EXPORT void Caller(PFNTEST pfnTest);
StructMod.cpp
#define STRUCTMOD_EXPORT extern "C" __declspec(dllexport)
#include "StructMod.h"
#include <tchar.h>
void Caller(PFNTEST pfnTest) {
CardEvent ce[2] = { { 2, 2011 }, { 3, 2005 } };
if (pfnTest) (*pfnTest)(ce, _countof(ce));
}
--------------------------------------------------------------------------------------------------------------------
C# 调用:
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace IntPtrTest
{
class Program
{
static void Main(string[] args)
{
TestD t = new TestD(Test);
Caller(t);
}
[StructLayout(LayoutKind.Sequential)]
public struct CardEvent
{
public uint CardNo;
public Int32 EvtYear;
}
delegate void TestD(IntPtr p, Int32 nEvt);
[DllImport("StructMod", EntryPoint = "Caller", CallingConvention = CallingConvention.Cdecl)]
private static extern void Caller(TestD t);
public static unsafe void Test(IntPtr p, Int32 nEvt)
{
Console.WriteLine("nEvt = " + nEvt.ToString() + Environment.NewLine);
for (int n = 0; n < nEvt; n++)
{
p = p + n * sizeof(CardEvent);
CardEvent ce = (CardEvent)Marshal.PtrToStructure(p, typeof(CardEvent));
Console.WriteLine("[{0}]", n);
Console.WriteLine("CardNo - " + ce.CardNo.ToString());
Console.WriteLine("EvtYear - " + ce.EvtYear.ToString());
}
}
}
}
楼主在 C# 中声明这个导出函数时,使用了并不对应的 CardEvent[] C# 数组类型。
正确的做法是: 在 C# 声明 lpOnRecvCardEvent 时,第二个参数应该是 IntPtr ,不是数组。
由于楼主的这个 VC DLL 可能是自己写的,我没办法给出正确代码。
我提供一份模拟代码做参考:
----------------------------------------------------------------------------------------------------
VC DLL:
StructMod.h
#pragma once
#include <Windows.h>
#ifndef STRUCTMOD_EXPORT
#define STRUCTMOD_EXPORT extern "C" __declspec(dllimport)
#endif
typedef struct _tagCardEvent {
DWORD CardNo;
INT32 EvtYear;
} CardEvent, *PCardEvent;
STRUCTMOD_EXPORT CardEvent;
STRUCTMOD_EXPORT PCardEvent;
typedef void CALLBACK PFNTEST(PCardEvent pce, INT32 nEvt);
STRUCTMOD_EXPORT void Caller(PFNTEST pfnTest);
StructMod.cpp
#define STRUCTMOD_EXPORT extern "C" __declspec(dllexport)
#include "StructMod.h"
#include <tchar.h>
void Caller(PFNTEST pfnTest) {
CardEvent ce[2] = { { 2, 2011 }, { 3, 2005 } };
if (pfnTest) (*pfnTest)(ce, _countof(ce));
}
--------------------------------------------------------------------------------------------------------------------
C# 调用:
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace IntPtrTest
{
class Program
{
static void Main(string[] args)
{
TestD t = new TestD(Test);
Caller(t);
}
[StructLayout(LayoutKind.Sequential)]
public struct CardEvent
{
public uint CardNo;
public Int32 EvtYear;
}
delegate void TestD(IntPtr p, Int32 nEvt);
[DllImport("StructMod", EntryPoint = "Caller", CallingConvention = CallingConvention.Cdecl)]
private static extern void Caller(TestD t);
public static unsafe void Test(IntPtr p, Int32 nEvt)
{
Console.WriteLine("nEvt = " + nEvt.ToString() + Environment.NewLine);
for (int n = 0; n < nEvt; n++)
{
p = p + n * sizeof(CardEvent);
CardEvent ce = (CardEvent)Marshal.PtrToStructure(p, typeof(CardEvent));
Console.WriteLine("[{0}]", n);
Console.WriteLine("CardNo - " + ce.CardNo.ToString());
Console.WriteLine("EvtYear - " + ce.EvtYear.ToString());
}
}
}
}
追问
感谢热心回复,但是对C++不了解,还是不知道问题在哪里
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询