我很困惑如何将句柄从.Net 传递给我的托管对象到非托管代码。现在我正在使用 C# 为 Oracle Siebel CRM 开发一种“驱动程序”。以及我如何面对如何将句柄传递给驱动程序 API 的问题有这样的方法:
ISCAPI ISC_RESULT CreateISCDriverInstance
/* in */(const ISC_STRING mediaTypeStr,
/* in */ const ISC_STRING languageCode,
/* in */ const ISC_STRING connectString,
/* in */ const struct ISC_KVParamList* datasetParams,
/* out */ ISC_DRIVER_HANDLE* handle);
我对最后一个参数 ISC_DRIVER_HANDLE* 句柄有问题。我想说它可能看起来很奇怪,但我没有 ISC_DRIVER_HANDLE 类型的定义。
据我所知,可以使用 GCHandle 来处理它......这是我关于如何实现它的愿景:
[STAThread]
[DllExport("CreateISCDriverInstance", CallingConvention = CallingConvention.StdCall)]
public static int CreateIscDriverInstance([MarshalAs(UnmanagedType.LPWStr)] string mediaTypeStr,
[MarshalAs(UnmanagedType.LPWStr)] string languageCode,
[MarshalAs(UnmanagedType.LPWStr)] string connectString,
[In] ref IscKvParamList datasetParams,
out IntPtr handle)
{
... // Here I'm doing something with incoming data
var drvEntryPointHandle = GCHandle.Alloc(EntryPoints, GCHandleType.Pinned);
handle = GCHandle.ToIntPtr(drvEntryPointHandle);
return (int) ScErrorCode.ScEcOk;
}
但是,在调用此方法后,我会遇到 CLR 崩溃:(对于跟踪量,我感到非常抱歉)
ModLoad: C:\Debug\DriverLibrary.dll
ModLoad: C:\Windows\SysWOW64\MSCOREE.DLL
ModLoad: C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll
ModLoad: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
ModLoad: C:\Windows\SysWOW64\MSVCR120_CLR0400.dll
(730.4a4): Unknown exception - code 04242420 (first chance)
ModLoad: C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\d1265d6159ea876f9d63ea4c1361b587\mscorlib.ni.dll
ModLoad: \DriverLibrary.dll
ModLoad: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll
ModLoad: C:\Windows\Microsoft.NET\Framework\v4.0.30319\diasymreader.dll
ModLoad: NLog.dll
.......................................
ModLoad: C:\Windows\assembly\NativeImages_v4.0.30319_32\System.Runteb92aa12#\ad1a5e8488b493088c4317191604dc81\System.Runtime.Serialization.ni.dll
(730.4a4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
问题是:如何将句柄从.Net 传递给托管对象到非托管应用程序? ps 附加信息。缺乏信息是这里的主要问题。Oracle 提供的文档非常混乱且不完整。如果有人对已应用于信息检索的工作有疑问...这里是原始文档的链接https://docs.oracle.com/cd/E14004_01/books/PDF/SiebCTIAdm.pdf(从 260p 开始。 )。
但是我有一些大约 10 年前用 Delphi 编写的示例。我将从那里提供一些我认为可能有用的代码。1) 函数 CreateISCDriverInstance(在 TicISCCommunicationDriver 类中)
function CreateISCDriverInstance(const AMediaTypeStr, ALanguageCode,
AConnectString: PWideChar; const AParams: TISCNamedParamList;
out ADriverHandle: THandle): HRESULT;
begin
try
ADriverHandle := TicISCCommunicationDriver.CreateInstance(AParams).Handle;
Result := SC_EC_OK;
except
Result := SC_EC_DRIVER_CREATION_ERR;
end;
end;
2)部分或TicISCCommunicationDriver定义:
TicISCCommunicationDriver = class(TObject)
strict private
class var
FInstance: TicISCCommunicationDriver;
...
var
FHandle: THandle;
...
3)构造函数:类函数TicISCCommunicationDriver.CreateInstance(const AParams: TISCNamedParamList): TicISCCommunicationDriver;如果未分配则开始(FInstance)然后 FInstance := TicISCCommunicationDriver.Create(AParams); 结果:= FInstance;结尾;
constructor TicISCCommunicationDriver.Create(const AParams: TISCNamedParamList);
var
IsDebug: boolean;
begin
inherited Create;
FHandle := THandle(@Self);
...
end;
我从来没有在 Delphi 中开发过任何东西,但是,据我所知 - 它是在 Delphi 上实现的单例模式。FHandle:THandle
它只是 TicISCCommunicationDriver 实例的句柄。在 Google 中搜索后,我发现 THandle 它是一个标识全局分配的动态内存对象的句柄。pps 我也尝试使用 HandleRef 找到解决方案,但它也没有帮助。