询问者
Isa中断 函数dll调用 (急)

问题
-
刚刚学C#没多久,碰到平台调用的问题,急死了~dll是用C++编写的,函数如下:
/*********************************************************************************************************
** Function name: IsaInitIntrrupt
** Descriptions: 初始化中断
** Input parameters: dwIRQNumber 中断号
** IRQ3、IRQ4...
** hIntrEvent 中断对应的事件
** Output parameters: pdwSysIntr 系统分配的逻辑中断号
** Returned value: ISA_NO_ERR 中断初始化成功
** ISA_NO_IRQ_NUM PC/104总线不能使用该中断号
** ISA_INIT_INTR_FAIL 中断初始化失败
*********************************************************************************************************/
epcIsa_API DWORD epcIsaInitIntrrupt( DWORD dwIRQNumber,
HANDLE hIntrEvent,
PDWORD pdwSysIntr);/*********************************************************************************************************
** Function name: epcIsaIntrruptDone
** Descriptions: 重新使能中断
** Input parameters: dwSysIntrNumber 逻辑中断号
** Output parameters:
** Returned value: ISA_NO_ERR 重新使能中断成功
** ISA_INTR_UNINIT 中断还没有初始化
*********************************************************************************************************/
epcIsa_API DWORD epcIsaIntrruptDone( DWORD dwSysIntrNumber);C++调用如下:
//定义全局变量
BOOL __GbExitIST; /* 中断服务线程是否退出 */
HANDLE __GhIrqEvent; /* 中断事件 */
DWORD __GdwIrqNum = IRQ9; /* 用户使用的IRQ 号 */
DWORD __GdwSysIntr; /* 系统分配的逻辑中断号 */
HANDLE __GhIst; /* 指向中断服务线程的句柄 */
DWORD __GdwIstID; /* 中断服务线程的ID *///添加中断线程
DWORD IntrruptServiceThread (PVOID pArg)
{
CPC104Dlg *dlg = (CPC104Dlg*)pArg;
DWORD dwRetVaule; /* 函数返回值 */while(__GbExitIST == FALSE) { /* 判断是否退出中断服务线程 */
ret = WaitForSingleObject(__GhIrqEvent, INFINITE); /* 等待中断事件发生 */
if(ret == WAIT_OBJECT_0) { /* 等到中断事件 */
/*
* 中断处理代码
*/
MessageBox(_T("Message From Intrrupt Service Thread!"));
epcIsaIntrruptDone(__GdwSysIntr); /* 处理完中断重新使能中断 */
}
}
return 0;
}//按钮点击事件
void CPC104Dlg::OnIntr()
{
DWORD dwRetVaule; /* 函数返回值 */
CButton *pBnTmp = NULL;
MessageBox(_T("This is An Example Of Intrrupt Service Thread!"));
__GhIrqEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
/* 创建中断处理事件 */
if(__GhIrqEvent == INVAILID_HANDLE_VAULE) { /* 创建事件失败 */
MessageBox(_T("Create Event Fail!"));
return;
}
/*
* 初始化中断
*/
dwRetVaule = epcIsaInitIntrrupt( __GdwIrqNum, /* 中断号,这里为IRQ9 */
__GhIrqEvent, /* 用户创建的中断事件 */
&__GdwSysIntr); /* 系统分配的逻辑中断号 */
if(dwRetVaule != ISA_NO_ERR) { /* 初始化中断失败 */
MessageBox(_T("Initialize Intrrupt Fail!"));
return;
}
__GbExitIST = FALSE; /* 设置不退出中断处理线程 */__GhIst = CreateThread( 0,
0,
(LPTHREAD_START_ROUTINE)IntrruptServiceThread,
this,
0,
&__GdwIstID);
if(__GhIst == INVAILID_HANDLE_VAULE) { /* 创建中断服务线程失败 */
MessageBox(_T("Create IST FAIL!"));
return;
}
pBnTmp = (CButton*)GetDlgItem(IDC_EXIT);
pBnTmp->EnableWindow(TRUE); /* 使能ExitIST 按扭 */
}请问在C#中如何调用以上DLL中的函数,以及初始化中断的主函数~~
- 已编辑 杰心 2012年3月16日 2:18
全部回复
-
Hi 杰心,
欢迎来到C#论坛。
若要声明一个方法使其具有来自 DLL 导出的实现,请执行下列操作:
- 使用 C# 关键字 static 和 extern 声明方法。
- 将 DllImport 属性附加到该方法。DllImport 属性允许您指定包含该方法的 DLL 的名称。通常的做法是用与导出的方法相同的名称命名 C# 方法,但也可以对 C# 方法使用不同的名称。
- 还可以为方法的参数和返回值指定自定义封送处理信息,这将重写 .NET Framework 的默认封送处理。
例子:使用 DllImport 属性通过调用
msvcrt.dll
中的puts
输出消息。using System; using System.Runtime.InteropServices; class PlatformInvokeTest { [DllImport("msvcrt.dll")] public static extern int puts(string c); [DllImport("msvcrt.dll")] internal static extern int _flushall(); public static void Main() { puts("Test"); _flushall(); } }
C# 与 C++ 数据类型对照
C++ C#
=====================================
WORD ushort
DWORD uint
UCHAR int/byte 大部分情况都可以使用int代替,而如果需要严格对齐的话则应该用bytebyte
UCHAR* string/IntPtr
unsigned char* [MarshalAs(UnmanagedType.LPArray)]byte[]/?(Intptr)
char* string
LPCTSTR string
LPTSTR [MarshalAs(UnmanagedType.LPTStr)] string
long int
ulong uint
Handle IntPtr
HWND IntPtr
void* IntPtr
int int
int* ref int
*int IntPtr
unsigned int uint
COLORREF uint更多的信息请参考MSDN平台调用教程:http://msdn.microsoft.com/zh-cn/library/aa288468(v=vs.71).aspx
祝你愉快!
Bob Shen [MSFT]
MSDN Community Support | Feedback to us
-
Hi 杰心,
在C#声明结构体之前需要加上
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
在C# 里声明函数的时候,参数前面加上ref 表示传地址。Bob Shen [MSFT]
MSDN Community Support | Feedback to us
-
谢谢你的回答,能帮我看看下面这段程序错在哪么?主程序到调用ZWA_DeviceOpen时总是弹出NotSupportedException!!
引用的DLL文件是C++写的:
ZWAPCM8208BTBSDRV_API DWORD ZWA_DeviceOpen(LPZWADEVINFO pstDevInfo,LPZWAPFN pstIsaFn,HANDLE *phDevHandle);
C#中调用为:
[System.Runtime.InteropServices.DllImport("ZwaPCM8208BTBSDrv.dll", SetLastError = true,EntryPoint ="ZWA_DeviceOpen")] public static extern uint ZWA_DeviceOpen(ref ZWADEVINFO pstDevInfo, ref ZWAPFN pstIsaFn, out uint phDevHandle);
主程序调用:
private void deviceOpenButton_Click(object sender, EventArgs e) { uint dwRet = 0; ZWADEVINFO stDevInfo = new ZWADEVINFO();/* 设备信息结构体变量 */ ZWAPFN stpFnTmp = new ZWAPFN();/* PC/104总线操作函数指针结构体 */ uint m_hPCM8208BT = 0;/* 接收设备操作句柄 */ stDevInfo.dwDevType = (uint)DeviceType.PCM8208BTBS; /* 设备类型号 */ stDevInfo.dwDevAddr = (uint)0x300; /* 设备基地址 */ stDevInfo.dwIrqNo = (uint)DeviceIRQ.IRQ3; /* 设备使用的IRQ 物理中断号 */ stpFnTmp.lpfnIsaIoByteR = new pfnIsaIobyteR(epcIsaLib.epcIsaIoByteR); /* 初始化PC/104 总线操作 */ stpFnTmp.lpfnIsaIoByteW = new pfnIsaIobyteW(epcIsaLib.epcIsaIoByteW); /* 接口函数指针 */ stpFnTmp.lpfnIsaIoWordR = new pfnIsaIoWordR(epcIsaLib.epcIsaIoWordR); stpFnTmp.lpfnIsaIoWordW = new pfnIsaIoWordW(epcIsaLib.epcIsaIoWordW); stpFnTmp.lpfnIsaInitSysIrq = new pfnIsaInitSysIrq(epcIsaLib.epcIsaInitIntrrupt); stpFnTmp.lpfnIsaDisableSysIrq = new pfnIsaDisableSysIrq(epcIsaLib.epcIsaIntrruptDisable); stpFnTmp.lpfnIsaReEnableSysIrq = new pfnIsaReEnableSysIrq(epcIsaLib.epcIsaIntrruptDone); dwRet = ZwaPCM8208BTBSDrvLib.ZWA_DeviceOpen(ref stDevInfo, ref stpFnTmp, out m_hPCM8208BT); //一到这句就会弹出NotSupportedException!!! if (dwRet != (uint)DeviceErrorCode.ERR_SUCCESS) { MessageBox.Show("打开设备失败!"); } }
任何杀不死我的困难只会让我更强大!!