Presentation is loading. Please wait.

Presentation is loading. Please wait.

RDNZL Raw DotNet Zupport for Lisp (?). Amsterdam, 2004-09-26Dr. Edmund Weitz2 But why? access to.NET libraries (XML, SOAP,...) fully "native" GUIs reflection,

Similar presentations

Presentation on theme: "RDNZL Raw DotNet Zupport for Lisp (?). Amsterdam, 2004-09-26Dr. Edmund Weitz2 But why? access to.NET libraries (XML, SOAP,...) fully "native" GUIs reflection,"— Presentation transcript:

1 RDNZL Raw DotNet Zupport for Lisp (?)

2 Amsterdam, Dr. Edmund Weitz2 But why? access to.NET libraries (XML, SOAP,...) fully "native" GUIs reflection, i.e. no header parsing learn C++ learn Windows API maybe it‘s fun?

3 Amsterdam, Dr. Edmund Weitz3 Current Status experimental... basic stuff works: –load assemblies –import types –invoke methods –get and set fields and properties –transparent handling of (some) Lisp types uses LispWorks FLI and MOP first public release: maybe in November

4 Amsterdam, Dr. Edmund Weitz4 Prior Art Dot-Scheme (Pedro Pinto, PLT Scheme) –C++ code partly reusable for RDNZL –FLI very different (more like ECL) JFLI (Rich Hickey, LispWorks) –uses JNI –good ideas for CLOS integration

5 Amsterdam, Dr. Edmund Weitz5 Managed C++ has full access to managed code managed code can be mixed with unmanaged code can export functions with C linkage (necessary for all CL FLIs) not possible with C#, J#, VB, etc.

6 Amsterdam, Dr. Edmund Weitz6 Representation of.NET objects - 1 class DotNetReference { public: DotNetReference(); DotNetReference(Object *o); ~DotNetReference(); Object *getObject(); private: void *ptr; };

7 Amsterdam, Dr. Edmund Weitz7 Representation of.NET objects - 2 DotNetReference::DotNetReference() : ptr(0) {} DotNetReference::DotNetReference(Object *o) { ptr = static_cast (GCHandle::Alloc(o)).ToPointer(); } DotNetReference::~DotNetReference() { if (ptr) { GCHandle::op_Explicit(ptr).Free(); } Object *DotNetReference::getObject() { return ptr ? dynamic_cast (GCHandle::op_Explicit(ptr).Target) : 0; }

8 Amsterdam, Dr. Edmund Weitz8 Representation of.NET objects - 3 // only excerpts class DotNetContainer { public: DotNetContainer(Object *o, Type *t); DotNetContainer(__int32 n); DotNetContainer(__wchar_t *s); Object *getContainerObject(); Type *getContainerType(); private: DotNetReference* object; DotNetReference* type; }; extern "C" { __declspec(dllexport) void *makeDotNetContainerFromInt(int n); __declspec(dllexport) void *makeDotNetContainerFromString(__wchar_t *s); __declspec(dllexport) int getDotNetContainerTypeStringLength(void *ptr); __declspec(dllexport) void getDotNetContainerTypeAsString(void *ptr, __wchar_t *s); __declspec(dllexport) int getDotNetContainerObjectStringLength(void *ptr); __declspec(dllexport) void getDotNetContainerObjectAsString(void *ptr, __wchar_t *s); __declspec(dllexport) int getDotNetContainerIntValue(void *ptr); __declspec(dllexport) void freeDotNetContainer(void *ptr); }

9 Amsterdam, Dr. Edmund Weitz9 Representation of.NET objects - 4 void DotNetContainer::init(Object *o, Type *t) { object = o ? new DotNetReference(o) : new DotNetReference(); type = t ? new DotNetReference(t) : new DotNetReference(); } DotNetContainer::DotNetContainer(Object *o, Type *t) { init(o, t); } DotNetContainer::DotNetContainer(__int32 n) { init(__box(n)); } __declspec(dllexport) void *makeDotNetContainerFromInt(int n) { return new DotNetContainer(n); } __declspec(dllexport) void getDotNetContainerObjectAsString(void *ptr, __wchar_t *s) { const __wchar_t __pin *temp = PtrToStringChars(static_cast (ptr)->getContainerObject()->ToString()); wcscpy(s, temp); } __declspec(dllexport) void freeDotNetContainer(void *ptr) { delete static_cast (ptr); }

10 Amsterdam, Dr. Edmund Weitz10 On the Lisp Side... (define-foreign-function (%free-dotnet-container "freeDotNetContainer") ((ptr :pointer)) :result-type :void) (defstruct dotnet-container pointer) (defun maybe-free-ptr (object) (when (dotnet-container-p object) (%free-dotnet-container (dotnet-container-pointer object)))) (add-special-free-action 'maybe-free-ptr)... (flag-special-free-action dotnet-container)

11 Amsterdam, Dr. Edmund Weitz11 Example: Invoking a Method __declspec(dllexport) void* invokeInstanceMember(void *target, __wchar_t *name, int nargs, void *args[]) { try { Object *realArgs[] = new Object*[nargs]; Type *realTypes[] = new Type*[nargs]; for (int i = 0; i < nargs; i++) { DotNetContainer *c = static_cast (args[i]); realArgs[i] = c->getContainerObject(); realTypes[i] = c->getContainerType(); } DotNetContainer *container = static_cast (target); Type *t = container->getContainerType(); MethodInfo *mi = t->GetMethod(name, realTypes); // todo: throw exception if mi == 0 Object *newInstance = mi->Invoke(container->getContainerObject(), realArgs); // InvocationResult is a wrapper which can handle void results and exceptions if (mi->ReturnType->Equals(__typeof(System::Void))) { return new InvocationResult(); } else { return new InvocationResult(newInstance); } } catch (Exception *e) { return new InvocationResult(e, true); }

12 Amsterdam, Dr. Edmund Weitz12 On the Lisp Side... (defun invoke-member (object method &rest args) (with-dynamic-foreign-objects () (let ((arg-pointers (allocate-dynamic-foreign-object :type :pointer :nelems (length args)))) (loop for arg in args for i from 0 do (setf (dereference arg-pointers :index i) (dotnet-container-pointer (box arg)))) (with-foreign-string (method-name element-count byte-count :external-format :unicode) method (declare (ignore element-count byte-count)) (get-invocation-result ;; handles GC, exceptions, "unboxing" (%invoke-instance-member ;; FLI call (dotnet-container-pointer object) method-name (length args) arg-pointers))))))

13 Amsterdam, Dr. Edmund Weitz13 Name Mangling.NET type System.String Lisp class.SYSTEM:STRING.NET type System.Runtime.InteropServices Lisp class.SYSTEM.RUNTIME:INTEROP-SERVICES not bijective, but see CLS not good, will be replaced by reader macros

14 Amsterdam, Dr. Edmund Weitz14 CLOS integration load assembly import public types, map to CLOS classes preserve class hierarchy create constructor(s) (new '.system:string #\a 3) create (CLOS) methods (.get-type "foo") create field/property accessors (setf (.name (new '.system.reflection::assembly-name)) "MyAssembly")

15 Amsterdam, Dr. Edmund Weitz15 Delegates clever trick (by Pedro Pinto) at runtime create CLR code for new delegate type Foo and method InvokeClosure with correct signature Foo inherits from managed C++ class DelegateAdapterBase InvokeClosure calls DelegateAdapterBase::invoke(Object* args []) DelegateAdapterBase constructor accepts (long) integer which is index into Lisp hash of closures invoke calls Lisp foreign callable with index and DotNetContainer array invoke knows about InvokeClosure 's signature via run-time reflection

16 Amsterdam, Dr. Edmund Weitz16 To Do better name mangling, reader macros (partly) integrate.NET exceptions into CL condition system convenience functions/macros for enumerations and arrays performance improvements porting to other Lisps (any volunteers?)

Download ppt "RDNZL Raw DotNet Zupport for Lisp (?). Amsterdam, 2004-09-26Dr. Edmund Weitz2 But why? access to.NET libraries (XML, SOAP,...) fully "native" GUIs reflection,"

Similar presentations

Ads by Google