I'm quite confused about how to pass handle to my managed object from .Net to unmanaged code. Now I'm developing kind of "driver" for Oracle Siebel CRM using C#. And how i faced with problem about how to pass handle to Driver API have such method:
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);
And i have the problem with last parameter ISC_DRIVER_HANDLE* handle. I want to say that it may looks quite weird, but i don't have a definition of ISC_DRIVER_HANDLE type.
As far as I know it's possible to use GCHandle to work with this... And here is my vision about how it should be implemented:
[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;
}
But, after call of this method i'll get the CLR crash: (i'm terrible sorry about amount of traces)
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.
Question is: How to pass handle to managed object from .Net in to unmanaged application? p.s. Additional info. Lack of information is main problem here. Documentation provided by Oracle are very confusing and incomplete. If anyone have some doubts about efforts that have been applied to information retrieval... Here is a link to original documentation https://docs.oracle.com/cd/E14004_01/books/PDF/SiebCTIAdm.pdf (starts from 260p.).
But I have some example which were written in Delphi about 10 years ago. I'll provide some code from there which I think may be useful. 1) Function CreateISCDriverInstance(in TicISCCommunicationDriver class)
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 or TicISCCommunicationDriver defenition:
TicISCCommunicationDriver = class(TObject)
strict private
class var
FInstance: TicISCCommunicationDriver;
...
var
FHandle: THandle;
...
3) Constructor: class function TicISCCommunicationDriver.CreateInstance(const AParams: TISCNamedParamList): TicISCCommunicationDriver; begin if not Assigned(FInstance) then FInstance := TicISCCommunicationDriver.Create(AParams); Result := FInstance; end;
constructor TicISCCommunicationDriver.Create(const AParams: TISCNamedParamList);
var
IsDebug: boolean;
begin
inherited Create;
FHandle := THandle(@Self);
...
end;
I've never developed anything in Delphi, but, as far as i can get - it's singleton pattern implemented on Delphi. And FHandle:THandle
it's just a handle to instance of TicISCCommunicationDriver.
After search in Google i found that THandle it's a handle identifying a globally allocated dynamic memory object.
p.p.s.
Also i tried to find the solution using HandleRef, but it doesn't helped too.
GCHandle
has no place for that parameter. That's used for operations like pinning managed memory. This handle is provided by the unmanaged code. It is an opaque pointer.The Delphi code, which incidentally I know from your other question to be a little wonky, declares this as a
THandle
. That's semantically off because I don't think this handle is really a Win32HANDLE
.However, it is safe to say that this handle is just an
IntPtr
. You deal with that parameter exactly as I stated in your previous question:The function yields a handle to its state, to the thing that the function just created. You remember it and then pass it on to the other functions that need that handle.