【发布时间】:2014-11-21 13:24:18
【问题描述】:
我很困惑如何将句柄从 .Net 传递给我的托管对象到非托管代码。现在我正在使用 C# 为 Oracle Siebel CRM 开发一种“驱动程序”。以及我如何面对如何将句柄传递给 Driver 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 传递到非托管应用程序? p.s.附加信息。 缺乏信息是这里的主要问题。 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) Part 或 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 找到解决方案,但也无济于事。
【问题讨论】:
-
你必须做到
out IntPtr handle。缺少的out足以使本机代码崩溃。 -
谢谢你,汉斯!我已经添加了修饰符。但这没有帮助。我遇到了同样的异常: ModLoad: 55010000 552be000 C:\Windows\assembly\NativeImages_v4.0.30319_32\System.Runteb92aa12#\ad1a5e8488b493088c4317191604dc81\System.Runtime.Serialization.ni.dll (22a8.1ba8): 访问冲突 - 代码c0000005(第一次机会)在任何异常处理之前报告第一次机会异常。可能会出现此异常并进行处理。
-
避免假设您只有一个错误。 Siebel 程序员在设计那个 api 时可能喝醉了。
-
是的,他们在开发软件和编写文档时一直喝醉了。但是我必须以某种方式处理这个问题:) 我假设问题出在句柄上,基于以下驱动程序加载过程的描述: 加载通信驱动程序的过程如下: 1 通道管理器调用驱动程序句柄方法APIVersion,检查驱动的API版本。
-
2 通道管理器调用驱动程序句柄方法CreateISCDriverInstance,创建驱动程序实例。 3 通道管理器调用驱动程序句柄方法 RequestCommandEventList,以检索该驱动程序支持的事件和命令列表。我有来自我的 DLL 和 Siebel 的跟踪,我看到应用程序在调用 CreateISCDriverInstance 之后和调用 RequestCommandEventList 之前崩溃。
标签: c# pinvoke unmanaged-memory