SCCERR EXOpenExport {VTHDOC hDoc, VTDWORD dwOutputId, VTDWORD dwSpecType,
VTLPVOID pSpec, VTDWORD dwFlags, VTSYSPARAM dwReserved, VTLPVOID pCallbackFunc,
VTSYSPARAM dwCallbackData, VTLPHEXPORT phExport);
从头文件中,我将参数简化为:
typedef VTSYSPARAM VTHDOC,VTLPHDOC *
typedef DWORD_PTR VTSYSPARAM
typedef unsigned long DWORD_PTR
typedef unsigned long VTDWORD
typedef VTVOID* VTLPVOID
#define VTVOID void
typedef VTHDOC VTHEXPORT, *VTLPEXPORT
These are for 32 bit windows
浏览了头文件、示例程序和文档,我发现:
1. pSpec 可以是缓冲区的指针或 NULL,所以我将其设置为 IntPtr.Zero(文档)。
2. 根据文档,dwFlags 和 dwReserved 必须由开发者设置为 0。
3. 如果不想处理回调,pCallbackFunc 可以设置为 NULL。
4. 最后两个参数基于我使用 [StructLayout(LayoutKind.Sequential)] 编写 C# 包装器的结构。然后,我实例化了一个对象,并通过首先使用 Marshal.AllocHGlobal(Marshal.SizeOf(instance)) 创建 IntPtr,然后获取地址值,将其作为 uint 传递给 dwCallbackData,将其作为 IntPtr 传递给 phExport,生成了参数。
最终的参数列表如下:
1. phDoc 作为 IntPtr,由之前调用的 DAOpenDocument 函数加载了一个地址。
2. dwOutputId 作为 uint 设置为 1535,表示 FI_JPEGFIF。
3. dwSpecType 作为 int 设置为 2,表示 IOTYPE_ANSIPATH。
4. pSpec 作为 IntPtr.Zero,输出将被写入其中。
5. dwFlags 作为 uint 设置为 0,按照指示。
6. dwReserved 作为 uint 设置为 0,按照指示。
7. pCallbackFunc 作为 IntPtr 设置为 NULL,因为我会处理结果。
8. dwCallBackDate 作为 uint,是一个结构体缓冲区的地址。
9. phExport 作为 IntPtr,指向另一个结构体缓冲区。
仍然从 API 中得到未定义错误。这意味着调用返回了一个在任何头文件中都没有定义的 961。过去,当我的参数类型选择不正确时,我也遇到过这种情况。
我开始使用 Interop Assistant,它有助于学习许多参数类型的转换方式。但是,它受限于我能否从头文件中正确获取本机类型的程度。例如,前面函数中使用的 hDoc 参数被定义为非文件系统句柄,因此尝试使用 Marshal 创建句柄,然后使用 IntPtr,最后它被证明是 int(实际上是 &phDoc 在此处使用)。
那么除了试错之外,还有更科学的方法吗?
Jim