尝试从 Oracle 的 Outside In API 互操作功能。
具有以下功能:
SCCERR EXOpenExport(VTHDOC hDoc, VTDWORD dwOutputId, VTDWORD dwSpecType,
VTLPVOID pSpec, VTDWORD dwFlags, VTSYSPARAM dwReserved,
VTLPVOID pCallbackFunc, VTSYSPARAM dwCallbackData, VTLPHEXPORT phExport);
从头文件中我将参数减少为:
#define VTVOID void
typedef VTSYSPARAM VTHDOC, VTLPHDOC *;
typedef DWORD_PTR VTSYSPARAM;
typedef unsigned long DWORD_PTR;
typedef unsigned long VTDWORD;
typedef VTVOID* VTLPVOID;
typedef VTHDOC VTHEXPORT, *VTLPEXPORT;
这些用于 32 位窗口。
浏览头文件、示例程序和文档,我发现:
-
pSpec
可能是指向缓冲区或 NULL
的指针,因此我将其设置为 >IntPtr.Zero
(文档)。
- 根据文档“必须由开发人员将其设置为 0”,
dwFlags
和 dwReserved
。
- 如果我不想处理回调,则可以将 pCallbackFunc 设置为 NULL。
- 最后两个基于我编写的使用
[StructLayout(LayoutKind.Sequential)]
的 C# 包装器的结构。然后实例化并生成参数,首先使用 Marshal.AllocHGlobal(Marshal.SizeOf(instance))
创建一个 IntPtr
,然后获取作为传递的地址值uint
用于 dwCallbackData
,IntPtr
用于 phExport
。
最终的参数列表如下:
-
phDoc
作为一个 IntPtr
,由之前调用的 DAOpenDocument
函数加载了地址。
-
dwOutputId
作为 uint
设置为 1535
,表示 FI_JPEGFIF
-
dwSpecType
作为 int
设置为 2
,表示 IOTYPE_ANSIPATH
-
pSpec
作为 IntPtr.Zero
,输出将写入其中
dwFlags
as uint
设置为 0
按照指示
dwReserved
as uint
设置为 >0
按照指示将
pCallbackFunc
作为 IntPtr
设置为 NULL
,因为我会将结果
dwCallBackData
处理为 < code>uint struct phExport
的缓冲区地址
- 作为
IntPtr
到另一个 struct buffer
仍然从 API 收到未定义的错误。这意味着调用返回一个未在任何头文件中定义的 961。过去,当我选择的参数类型不正确时,我就会遇到这种情况。
我开始使用 Interop Assistant,它有助于了解有多少参数类型被翻译。然而,它受到我从头文件中收集正确的本机类型的能力的限制。例如,前面函数中使用的 hDoc 参数被定义为非文件系统句柄,因此尝试使用 Marshal 创建句柄,然后使用 IntPtr ,最后结果是一个int
(实际上是这里用的&phDoc
)。
那么,除了反复试验之外,还有更科学的方法吗?
吉姆
Trying to Interop a functionality from the Outside In API from Oracle.
Have the following function:
SCCERR EXOpenExport(VTHDOC hDoc, VTDWORD dwOutputId, VTDWORD dwSpecType,
VTLPVOID pSpec, VTDWORD dwFlags, VTSYSPARAM dwReserved,
VTLPVOID pCallbackFunc, VTSYSPARAM dwCallbackData, VTLPHEXPORT phExport);
From the header files I reduced the parameters to:
#define VTVOID void
typedef VTSYSPARAM VTHDOC, VTLPHDOC *;
typedef DWORD_PTR VTSYSPARAM;
typedef unsigned long DWORD_PTR;
typedef unsigned long VTDWORD;
typedef VTVOID* VTLPVOID;
typedef VTHDOC VTHEXPORT, *VTLPEXPORT;
These are for 32 bit windows.
Going through the header files, the example programs, and the documentation I found:
- That
pSpec
could be a pointer to a buffer or NULL
, so I set it to a IntPtr.Zero
(documentation).
- That
dwFlags
and dwReserved
according to the documentation "Must be set by the developer to 0".
- That
pCallbackFunc
can be set to NULL
if I don't want to handle callbacks.
- That the last two are based on structs that I wrote C# wrappers for using the
[StructLayout(LayoutKind.Sequential)]
. Then instatiated an instance and generated the parameters by first creating an IntPtr
with Marshal.AllocHGlobal(Marshal.SizeOf(instance))
, then getting the address value which is passed as a uint
for dwCallbackData
and a IntPtr
for phExport
.
The final parameter list is as follows:
phDoc
as an IntPtr
which was loaded with an address by the DAOpenDocument
function called before.
dwOutputId
as uint
set to 1535
which represents FI_JPEGFIF
dwSpecType
as int
set to 2
which represents IOTYPE_ANSIPATH
pSpec
as an IntPtr.Zero
where the output will be written
dwFlags
as uint
set to 0
as directed
dwReserved
as uint
set to 0
as directed
pCallbackFunc
as IntPtr
set to NULL
as I will handle results
dwCallBackData
as uint
the address of a buffer for a struct
phExport
as IntPtr
to another struct buffer
Still get an undefined error from the API. Meaning that the call returns a 961 which is not defined in any of the header files. In the past I have gotten this when my choice of parameter types are incorrect.
I started out using Interop Assistant which was helpful in learning how many of the parameter types get translated. It is however limited by how well I am able to glean the correct native type from the header files. For example the hDoc
parameter used in the preceding function was defined as a non-filesytem handle, so attempted to use Marshal
to create a handle, then used an IntPtr
, and finally it turned out to be an int
(actually it was &phDoc
used here).
So is there a more scientific way of doing this, other than trial and error?
Jim
发布评论
评论(1)
您的定义:
不正确 -
DWORD_PTR
定义为:反过来又定义为:
属性
__int3264
记录在 这里,我复制了最重要的一点:当您编组 C“类型”(例如
DWORD_PTR
)时,其大小取决于平台指针大小,这通常是操作系统参数的情况(例如LPARAM
、WPARAM
、LRESULT
、SIZE_T
等)(名称VTSYSPARAM
似乎表明了这一点),您应该使用IntPtr
code>,而不是uint
。基本上:
应该是:
然后它应该可以工作,如果没有,您需要确保在以下情况下没有犯类似的错误整理必要的结构。
Your definition:
Is incorrect —
DWORD_PTR
is defined as:Which in turn is defined as:
The attribute
__int3264
is documented here, I am reproducing the most important bit:When you are marshaling C "types" such as
DWORD_PTR
whose size depends on the platform pointer size which is often the case with the OS parameters (such asLPARAM
,WPARAM
,LRESULT
,SIZE_T
, etc) which the nameVTSYSPARAM
appears to suggest, you should useIntPtr
, notuint
.Basically:
Should be:
Then it should work, and if it doesn't you need to make sure you didn't make a similar mistake when marshaling the necessary structures.