以下简约示例适用于IronPython(NodaTime可在http://nodatime.org/免费获得):
import clr
clr.AddReference('NodaTime')
from NodaTime import SystemClock
print SystemClock.Instance.ToString()
print SystemClock.Instance.Now
按预期输出:
NodaTime.SystemClock
2016-10-07T13:25:17Z
但是,以下使用mscorlib_tlb(.NET互操作层)的Delphi代码失败:
const
CLASS_CLRMetaHost: TGUID = '{9280188D-0E8E-4867-B30C-7FA83884E8DE}';
procedure CLRCreateInstance(const rclsid: TCLSID; const riid: TIID;
out pv); safecall; external 'mscoree';
var
CLR: ICLRMetaHost;
Runtime: ICLRRuntimeInfo;
Host: ICLRRuntimeHost;
CorHost: ICorRuntimeHost;
Domain: AppDomain;
Assmbly: Assembly;
Typ: Type_;
SystemClock: OleVariant;
V: IUnknown;
begin
CLRCreateInstance(CLASS_CLRMetaHost, IID_ICLRMetaHost, CLR);
Runtime := ICLRRuntimeInfo(CLR.GetRuntime('v2.0.50727', IID_ICLRRuntimeInfo));
Host := ICLRRuntimeHost(Runtime.GetInterface(CLASS_CLRRuntimeHost, IID_ICLRRuntimeHost));
Host.Start;
CorHost := ICorRuntimeHost(Runtime.GetInterface(CLASS_CorRuntimeHost, IID_ICorRuntimeHost));
CorHost.CreateDomain('', nil, V);
Domain := V as AppDomain;
Assmbly := Domain.Load_2('NodaTime');
Typ := Assmbly.GetType_2('NodaTime.SystemClock');
SystemClock := Typ.GetField_2('Instance').GetValue(Null);
WriteLn(Typ.GetMethod_6('ToString').Invoke_3(SystemClock, nil));
Typ.GetProperty_7('Now').GetValue(SystemClock, nil);
end.
输出:
NodaTime.SystemClock
Exception EOleException in module test.EXE at 000DD9A2.
Значение не попадает в ожидаемый диапазон.
(异常代码实际上是0x80070057 E_INVALIDARG“一个或多个参数无效”。奇怪 - 我没有传递任何参数。)
问题在于NodaTime.SystemClock.Now属性返回一个struct(值类型)NodaTime.Instant。似乎NodaTime.Instant的IsLayoutSequential = True,因此结构应该是非托管兼容的。
从非托管代码中检索NodaTime.SystemClock.Now的正确方法是什么?