当C#遇到函数指针及相关结构体——请教关于C#调用C编写的DLL时头文件重新申明的问题

ELFBYW 2009-03-16 10:06:05
C#中不包含函数指针的概念,而函数指针又是在C头文件中常使用的接口封装模式。因为刚刚接触C#不久,对于“委托”的理解尚属浅薄,近期接触的一个问题令我纠结了很久。从网上查找了许多相关文档,但知识点有些纷乱,还是到这里来寻求一下帮助。


#ifdef __cplusplus
extern "C" {
#endif

typedef HDISCFILE (*Open )(HDISC hDisc, const wchar_t *filename, A_UINT32 dwOpenMethod, A_UINT32 dwNodeType, A_UINT64 llFileSize);

typedef A_INT32 (*Read )(const HDISCFILE hDiscFile, A_UINT8 *buffer, A_UINT32 count);

typedef A_INT32 (*Write )(const HDISCFILE hDiscFile, A_UINT8 *buffer, A_UINT32 count);

typedef A_UINT64 (*Seek )(const HDISCFILE hDiscFile, A_INT64 offset, A_INT32 origin);

typedef A_UINT64 (*Size )(const HDISCFILE hDiscFile);

typedef A_INT32 (*Close )(const HDISCFILE hDiscFile);

typedef HFIND (*FindFirstFile )(HDISC hDisc, const wchar_t *filename, FindFileData *pFileData);

typedef A_INT32 (*FindNextFile )(HDISC hDisc, HFIND hFind, FindFileData *pFileData);

typedef A_INT32 (*FindClose )(HDISC hDisc, HFIND hFind);

typedef A_INT32 (*DeleteFile)(HDISC hDisc, wchar_t * FileName);

typedef A_INT32 (*CreateDir )(HDISC hDisc, const wchar_t *pathname);

typedef A_INT32 (*DeleteDirectory)(HDISC hDisc, wchar_t * PathName);

typedef A_INT32 (*FileIsExist)(HDISC hDisc, wchar_t * FileName);

typedef A_INT32 (*DirectoryIsExist)(HDISC hDisc, wchar_t * PathName);

typedef A_INT32 (*GetFreeCapacity)(HDISC hDisc, A_UINT32 * dwTotal, A_UINT32 * dwMaxSequential);


typedef struct tagIOParam
{
A_UINT32 cbSize;
Open open;
Read read;
Write write;
Seek seek;
Size size;
Close close;

CreateDir createdir;
FindFirstFile findfirstfile;
FindNextFile findnextfile;
FindClose findclose;
DeleteFile deletefile;
DeleteDirectory deletedirectory;
FileIsExist fileexist;
DirectoryIsExist dirextoryexist;
GetFreeCapacity getfreecapacity;
HDISC hDisc;
A_UINT32 Reseved1;
}IOParam, *HIOParam;

MEIDUM_IO_API A_BOOL InitIOParam(wchar_t * lptPath, HIOParam *phParam, wchar_t *lptVolumeName);

MEIDUM_IO_API void UninitIOParam(HIOParam hParam);

#ifdef __cplusplus
}
#endif

这是我需要使用的C语言编写的DLL的其中一个头文件,主要控制文件在硬盘及光盘上的读写操作,其中大量使用函数指针来进行操作,希望各位C#高人给予指导,在我的上层app中如需调用该DLL,对此头文件应进行怎样的重新申明。
...全文
416 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
ELFBYW 2009-03-16
  • 打赏
  • 举报
回复
可否给出个例子说明一下如何用delegate来代替函数指针?
结构体是否不需要修改就可以直接放入C#的重新申明代码中?
没有在相关资料中看到关于对齐方式的问题,这个指的是什么?
ztenv 2009-03-16
  • 打赏
  • 举报
回复
函数指针可以用delegate来代替;结构体还是可以用的,要注意声明类型及对齐方式;
VirtualDesktop 2009-03-16
  • 打赏
  • 举报
回复
我给个例子给你
这个是C++里面的函数指针以及调用定义:

typedef void (__stdcall *delegate_GetPtr)(const void*);
typedef void (__stdcall *delegate_OnRequest)(const char* info);
typedef void (__stdcall *delegate_OnCancel)();
typedef void (__stdcall *delegate_OnError)();
typedef void (__stdcall *delegate_OnComplete)();
typedef void (__stdcall *delegate_OnProgress)(int percent);


void __stdcall SetEvents
(
delegate_GetPtr ptr,
delegate_OnRequest req,
delegate_OnCancel can,
delegate_OnError err,
delegate_OnComplete cmpl,
delegate_OnProgress prg
)
{
//这里实现内容省略
}



下面是C#函数指针变成delegate的例子


delegate void delegate_GetWrapperPtr(IntPtr ptr);

delegate void delegate_OnRequest(string Info);

/// <summary>
/// 无参函数指针
/// </summary>
delegate void delegate_NoParamFuncPtr();

delegate void delegate_OnProgress(int percent);

//下面是调用SetEvents,注意和上面C++原型的对比
[DllImport(_dll_path_,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall,
EntryPoint = "SetEvents")]
private static extern void SetEvents(
[MarshalAs(UnmanagedType.FunctionPtr)]
delegate_GetWrapperPtr ptr,
[MarshalAs(UnmanagedType.FunctionPtr)]
delegate_OnRequest req,
[MarshalAs(UnmanagedType.FunctionPtr)]
delegate_NoParamFuncPtr can,
[MarshalAs(UnmanagedType.FunctionPtr)]
delegate_NoParamFuncPtr err,
[MarshalAs(UnmanagedType.FunctionPtr)]
delegate_NoParamFuncPtr cmp,
[MarshalAs(UnmanagedType.FunctionPtr)]
delegate_OnProgress prg
);



怎么样,看出名堂没?
冬天的糊涂神 2009-03-16
  • 打赏
  • 举报
回复
[DllImport("USER32.DLL")]
static extern int SendMessage(
IntPtr hwnd,
int wMsg,
int wParam,
capErrorCallback lParam
);

结构体,在C# 里面可以用类或者结构体实现

如果是指针

传入参数面前加ref
nmfengyun 2009-03-16
  • 打赏
  • 举报
回复
C#一般不使用指针,只有在不安全代码里使用指针.
lateknow 2009-03-16
  • 打赏
  • 举报
回复
用delegate来代替函数指针:
public delegate int capErrorCallback(
IntPtr hWnd,
int nID,
string lpsz
);
capErrorCallback m_errorCallBack = new capErrorCallback(this.capErrorCallback);

SendMessage(m_hwnd, WM_CAP_SET_CALLBACK_ERRORA, 0, m_errorCallBack);

[DllImport("USER32.DLL")]
static extern int SendMessage(
IntPtr hwnd,
int wMsg,
int wParam,
capErrorCallback lParam
);

结构体要修改能与C的结构体一样的类型.
杰克CZ 2009-03-16
  • 打赏
  • 举报
回复
指针用delegate,数据结构需要自己声明
cppfaq 2009-03-16
  • 打赏
  • 举报
回复
C#调用C++动态链接库中的函数指针与函数指针结构
http://www.dreamdu.com/blog/2008/04/25/cs_cpp_functionpointer/

111,126

社区成员

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

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

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