用C#调用VC++的dll,参数是指向数组的Pvoid,求教~

ncscharles 2012-05-24 03:12:47
在C++文件中,有如下定义:
一个函数指针:
#define CALLBACK __stdcall
typedef VOID (CALLBACK* P_EVENT)( INT eNo, PVOID pData, PVOID pContxt );

一个结构体:
typedef struct tagSTR_DEF{
P_EVENT pRoutine; // CallBack Function
PVOID pMeasContext; // CallBack Function Use Variable
PVOID pTransBuffer; // Exchanges Buffer
} STR_DEF, *PSTR_DEF;

一个函数:
trans_StartA( int Device, PSTR_DEF pStr );


在C++工程中使用如下代码完成调用:
WORD m_Buffer[512];

STR_DEF acqInfo;
acqInfo.pRoutine = CallbackAcquire; // Callback function
acqInfo.pMeasContext = this;
acqInfo.pTransBuffer = m_Buffer;

CallbackAcquire( INT eNo, PVOID pData, PVOID pContxt )
{

//将m_Buffer中的数据输出
}


trans_StartA(Device, &acqInfo);

工作的目的是用C#调用这个函数

现在的C#代码是:

public delegate void P_EVENT(UInt32 eNo, ref ushort[] pData, ref UInt32 pContxt);

[StructLayout(LayoutKind.Sequential)]
public struct STR_DEF
{
[MarshalAs(UnmanagedType.FunctionPtr)]
public P_EVENT pRoutine;

[MarshalAs(UnmanagedType.U4)]
public Int32 pMeasContext;

unsafe public fixed ushort pTransBuffer[512];

[DllImport("trans.dll")]
public static extern UInt32 trans_StartA(UInt32 Device, ref STR_DEF pStr);

short[] Matrix = new short[512];
int Device = 0;

private void button2_Click(object sender, EventArgs e)
{

STR_DEF acqInfo;
acqInfo.pRoutine = new P_EVENT(CallbackAcquire);
acqInfo.pMeasContext = this.Handle;
acqInfo.pTransBuffer = Matrix;

trans_StartA(0, ref acqInfo);
}

public void CallbackAcquire(UInt32 eNo, IntPtr pData, IntPtr pContxt)
{
UInt32 a = eNo;
Marshal.Copy(pData, Matrix, 0, 512);
}


现在的结果是函数返回值都是正确的,但是Matrix数组中的数据全为零,有人说是应该根据地址读内存,有些人说是地址错误。应该怎么实现trans_StartA()的功能呢?请大家赐教,谢谢~
...全文
218 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
ncscharles 2012-05-30
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]
你要不这样写试试

C# code
short* arr = stackalloc short[512];
acqInfo.pTransBuffer = (IntPtr)arr;
for (int i = 0; i < arr1.Length; ++i)
{
Matrix[i] = (char)arr[i];
}
[/Quote]

这样的话Matrix里面始终是全是零
__天涯寻梦 2012-05-29
  • 打赏
  • 举报
回复
你要不这样写试试
short* arr = stackalloc short[512];
acqInfo.pTransBuffer = (IntPtr)arr;
for (int i = 0; i < arr1.Length; ++i)
{
Matrix[i] = (char)arr[i];
}
ncscharles 2012-05-29
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]
或者可以尝试这个函数

IntPtr m_Buffer = Marshal.AllocHGlobal(1024);
....
Marshal.FreeHGlobal(m_Buffer)
[/Quote]
我先下了个Microsoft P/Invoke Interop Assistant 生成了C#代码,并且用了上述你提到的这两个函数:

IntPtr m_Buffer = Marshal.AllocHGlobal(1024);

//以下代码写在按钮点击事件中
tagSTR_DEF acqInfo;
... //给结构体中成员赋值
acqInfo.pTransBuffer=m_Buffer;

trans_StartA(0, ref acqInfo);
Marshal.Copy(m_Buffer, Matrix, 0, 512);//Matrix是char类型512长度一维数组

第一次运行时数据错误,第二次数据正确,第三次及以后的测量数据都是错误的,trans_StartA函数返回值在第一和二次测量时是正确的,以后都是错误的,请问可能是什么原因呢?

目前尝试过的有 1,在按钮点击事件中分配内存;2,执行完Marshal.Copy后释放内存Marshal.FreeHGlobal(m_Buffer)都没有效果,甚至第二次的采集也得不到正确的结果.





cnfixit 2012-05-24
  • 打赏
  • 举报
回复
或者可以尝试这个函数

IntPtr m_Buffer = Marshal.AllocHGlobal(1024);
....
Marshal.FreeHGlobal(m_Buffer)
cnfixit 2012-05-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

引用 1 楼 的回复:
Microsoft P/Invoke Interop Assistant 生成

C# code



/// Return Type: void
///eNo: INT->int
///pData: PVOID->void*
///pContxt: PVOID->void*
[System.Runtime.InteropServices.Unma……
[/Quote]

看看这个吧希望对你有帮助
http://www.cnblogs.com/namek/archive/2010/08/25/1808154.html
ncscharles 2012-05-24
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
Microsoft P/Invoke Interop Assistant 生成

C# code



/// Return Type: void
///eNo: INT->int
///pData: PVOID->void*
///pContxt: PVOID->void*
[System.Runtime.InteropServices.UnmanagedFunctionPo……
[/Quote]


谢谢,那么我在给结构体中的成员赋值的时候,C++程序中这个acqInfo.pTransBuffer = m_Buffer;应该怎么赋值呢?是用C#中数组的指针吗?怎么用?谢谢~~

cnfixit 2012-05-24
  • 打赏
  • 举报
回复
Microsoft P/Invoke Interop Assistant 生成


/// Return Type: void
///eNo: INT->int
///pData: PVOID->void*
///pContxt: PVOID->void*
[System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.StdCall)]
public delegate void P_EVENT(int eNo, System.IntPtr pData, System.IntPtr pContxt);

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct tagSTR_DEF {

/// P_EVENT
public P_EVENT pRoutine;

/// PVOID->void*
public System.IntPtr pMeasContext;

/// PVOID->void*
public System.IntPtr pTransBuffer;
}

public partial class NativeMethods {

/// Return Type: void
///Device: int
///pStr: PSTR_DEF->tagSTR_DEF*
[System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="trans_StartA")]
public static extern void trans_StartA(int Device, ref tagSTR_DEF pStr) ;

}


110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧