日期:2014-05-20  浏览次数:21202 次

关于C#调用带有回调参数的API
这几天使用C#调用PB API来分析pb的源代码文件,(在此严重鄙视PB,人家的源码都是文本,就你的非要自己捣鼓),其中一个API原型是这样的

int PBORCA_LibraryDirectory ( HPBORCA hORCASession, LPSTR lpszLibName, LPSTR lpszLibComments, int iCmntsBuffSize, PBORCA_LISTPROC pListProc, LPVOID pUserData ); 


参数说明

 
hORCASession 
 Handle to previously established ORCA session 
 
lpszLibName 
 Pointer to a string whose value is the filename of the library for which you want directory information 
 
lpszLibComments 
 Pointer to a buffer in which ORCA will put comments stored with the library 
 
iCmntsBuffSize 
 Size of the buffer pointed to by lpszLibComments 
 
pListProc 
 Pointer to the PBORCA_LibraryDirectory callback function. The callback function is called for each entry in the library 
The information ORCA passes to the callback function is entry name, comments, size of entry, and modification time, stored in a structure of type PBORCA_DIRENTRY 

 
pUserData 
 Pointer to user data to be passed to the PBORCA_LibraryDirectory callback function 
The user data typically includes the buffer or a pointer to the buffer in which the callback function formats the directory information as well as information about the size of the buffer 
 
其中pListProc作为回调函数,定义如下

typedef void (FAR PASCAL *PBORCA_LISTPROC) ( PPBORCA_DIRENTRY, LPVOID ); 

参数说明
PPBORCA_DIRENTRY 
 Pointer to the structure PBORCA_DIRENTRY, described next 
 
LPVOID 
 Long pointer to user data  
结构体PBORCA_DIRENTRY structure如下
typedef struct pborca_direntry 

CHAR szComments[PBORCA_MAXCOMMENT + 1]; 
LONG lCreateTime; 
LONG lEntrySize; 
LPSTR lpszEntryName;
 PBORCA_TYPE otEntryType;} 
PBORCA_DIRENTRY, FAR *PPBORCA_DIRENTRY; 

以上的详细参考资料在
http://manuals.sybase.com/onlinebooks/group-pb/adt0650e/orca/@Generic__BookTextView/7001;pt=4344;lang=zh#X




------解决方案--------------------
C\C++ 中的 char是类型一个字节

C# 中的 char类型,所以转换的时候要用byte取代C\C++中的char

大概是这样:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = PBORCA_MAXCOMMENT + 1)]
public byte[] szComments; // Buffer for entry info 

参考EnumWindows标准API回调的使用:
C# code

using System.Runtime.InteropServices;

public delegate bool WNDENUMPROC(IntPtr hwnd, int lParam);

[DllImport("user32.dll")]
public static extern int EnumWindows(WNDENUMPROC lpEnumFunc, int lParam);

public static bool EnumFunc(IntPtr hwnd, int lParam)
{
    Console.WriteLine("Window handle is " + hwnd);
    return true;
}

private void button1_Click(object sender, EventArgs e)
{
    EnumWindows(EnumFunc, 0);
}

------解决方案--------------------
int PBORCA_LibraryDirectory ( HPBORCA hORCASession, LPSTR lpszLibName, LPSTR lpszLibComments, int iCmntsBuffSize, PBORCA_LISTPROC pListProc, LPVOID pUserData ); 

从函数原型的字面意思很难猜出 LPSTR lpszLibName, LPSTR lpszLibComments
这两个是传入还是传出了

传入用 string就可以了
传出用 StringBuilder

PBORCA_DIRENTRY这个结构里面的 LPSTR lpszEntryName; 
这个可能会有点麻烦,这个应该是传出一个字符串
如果文档中没有定义的话,那这个应该是传出一个指针

你可以尝试定义为 IntPtr,然后用
Marshal.PtrToStringAnsi 
或者 PtrToStringAuto 或者 PtrToStringBSTR 或者 PtrToStringUni 转换一下