1 / 16

RDNZL

RDNZL. R aw D ot N et Z upport for L isp (?). 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?. Current Status. experimental... basic stuff works: load assemblies import types

alexa
Télécharger la présentation

RDNZL

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. RDNZL Raw DotNet Zupport for Lisp (?)

  2. 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? Dr. Edmund Weitz

  3. 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 Dr. Edmund Weitz

  4. 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 Dr. Edmund Weitz

  5. 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. Dr. Edmund Weitz

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

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

  8. 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); } Dr. Edmund Weitz

  9. 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<DotNetContainer *>(ptr)->getContainerObject()->ToString()); wcscpy(s, temp); } __declspec(dllexport) void freeDotNetContainer(void *ptr) { delete static_cast<DotNetContainer *>(ptr); } Dr. Edmund Weitz

  10. 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) Dr. Edmund Weitz

  11. 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<DotNetContainer *>(args[i]); realArgs[i] = c->getContainerObject(); realTypes[i] = c->getContainerType(); } DotNetContainer *container = static_cast<DotNetContainer *>(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); } } Dr. Edmund Weitz

  12. 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)))))) Dr. Edmund Weitz

  13. 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 Dr. Edmund Weitz

  14. 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") Dr. Edmund Weitz

  15. 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 Dr. Edmund Weitz

  16. 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?) Dr. Edmund Weitz

More Related