<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Again, ample evidence that I should not quit my day job any time soon and stride boldy into the world of software development. I would probably trip and break my nose in the fall.<div><br></div><div>The problem looks to be one of passing the wrong type of argument. The C function I am calling is defined as </div><div><br></div><div>void* invokeInstanceMember(const __wchar_t *methodName, void *target, int nargs, void *args[])</div><div><br></div><div>h-to-ffi.sh interprets that to be</div><div><br></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">(function ("/cygdrive/d/rdnzl-cpp-0.7.1/RDNZL/ffi-headers.h" 55)<br> "invokeInstanceMember"<br> (function<br> ((pointer (unsigned-short ())) (pointer (void ())) (int ()) (pointer (pointer (void ()))) )<br> (pointer (void ()))) (extern))</span></font></div><div><br></div><div>Then, given the following definitions:</div><div><br></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">(defun %invoke-instance-member (method-name type nargs args)<br> (ccl::with-native-utf-16-cstr (mn method-name)<br> (#_invokeInstanceMember mn type nargs args)))</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;"><br></span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">(defun test-invoke-2 ()<br> (let ((obj (make-type-from-name "System.Reflection.Assembly")))<br> (%invoke-instance-member "ToString" (pointer obj) 0 (ccl:%null-ptr))))<br><br>(defun test-invoke-3 ()<br> (let ((obj (make-type-from-name "System.Reflection.Assembly"))<br></span></font><span class="Apple-tab-span" style="white-space:pre"><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;"> </span></font></span><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">(type (box* "System.Reflection.Assembly")))<br> (ccl:rletz ((ptr (:array :address 1)))<br> (setf (ccl:paref ptr (:array :address) 0) type)<br> (%invoke-instance-member "GetType" (pointer obj) 1 ptr))))</span></font></div><div><br></div><div>I call (test-invoke-2) and all is hunky-dorey, but I try (test-invoke-3) and all heck breaks loose. I have imagined, and tried a couple different ways of representing an array of pointers, but clearly I am not imaginative enough.</div><div><br></div><div>It would be interesting to know if anyone else has tried calling foreign functions that have arguments of type void *args[]. I mean other than the code in cocoa-ide/start.lisp that I based the code in test-invoke-3 off of.</div><div><br></div><div>Cheers,</div><div>John</div><div> </div><div><br></div><div>(unwind-protect</div><div><div><div>On Oct 12, 2009, at 3:51 PM, Gary Byers wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>'exception' in this context almost certainly means machine-level exception<br>(e.g., attempt to reference memory that isn't there, attempt to execute<br>an illegal instruction ...) and doesn't likely refer to a C++ runtime<br>exception.<br><br>Beyond the fact that it can show a backtrace of the lisp stack leading<br>up to the ff-call, CCL's kernel debugger isn't very useful for debugging<br>exceptions that occur in foreign (C, C++) code. There are some (somewhat<br>Unix-centric) notes on using GDB at:<br><br><<a href="http://trac.clozure.com/openmcl/wiki/CclUnderGdb">http://trac.clozure.com/openmcl/wiki/CclUnderGdb</a>><br><br>Native Windows debuggers may work better for debugging crashes that occur<br>in Windows dlls; it's been a long time since I've tried to run CCL under<br>something like WinDbg, and I don't remember whether there were issues or<br>what they were.<br><br>I suppose that there are other possibilities, but I'd be most suspicious<br>of the FFI/CFFI code: passing the wrong number/types of arguments to a<br>C[++] function can certainly lead to a memory fault or other type of<br>machine exception.<br><br>[It varies a bit by platform, but CCL isn't always consistent about telling<br>you what general kind of machine exception occurred when that exception<br>occurred in foreign code; on OSX, trying to FF-CALL a null pointer enters<br>the kernel debugger with a (very) slightly more informative message:<br><br>? (ff-call (%null-ptr) :void)<br>Unhandled exception 10 at 0x0, context->regs at #xb029b8f0<br>Exception occurred while executing foreign code<br>? for help<br>[2086] Clozure CL kernel debugger:<br><br>The "unhandled exception 10" means "bus error" (SIGBUS = 10), which is<br>at least a little better than saying nothing in this case.]<br><br>On Mon, 12 Oct 2009, John Miller wrote:<br><br><blockquote type="cite">All,<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">On a wild hair, it seemed like it might be useful to have CCL running on my Windows XP 32-bit machine at work and use it to access Excel and Outlook using Dr. Edi Weitz's RDNZL (<a href="http://weitz.de/rdnzl/">http://weitz.de/rdnzl/</a>) package. Doing this has turned out to be more difficult than I thought. I built the FFI portion of the code using CFFI to look as close as possible to the FFI interfaces defined for the other lisps.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">For some things the FFI works. For example:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">? (make-type-from-name "System.Reflection.Assembly")<br></blockquote><blockquote type="cite">#<CONTAINER System.Type #x1532E08><br></blockquote><blockquote type="cite">? (import-assembly "mscorlib")<br></blockquote><blockquote type="cite">#<CONTAINER System.Reflection.Assembly #x1532EA8><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">But if I try to get fancy:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">? (import-types "System.Windows.Forms" "MessageBox")<br></blockquote><blockquote type="cite">%eax = 0x00faf00c<br></blockquote><blockquote type="cite">%ecx = 0x00000000<br></blockquote><blockquote type="cite">%edx = 0x00000002<br></blockquote><blockquote type="cite">%ebx = 0x79f7697c<br></blockquote><blockquote type="cite">%esp = 0x00faf008<br></blockquote><blockquote type="cite">%ebp = 0x00faf05c<br></blockquote><blockquote type="cite">%esi = 0x00faf094<br></blockquote><blockquote type="cite">%edi = 0x0040a958<br></blockquote><blockquote type="cite">%eip = 0x7c812a6b<br></blockquote><blockquote type="cite">%eflags = 0x00000206<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">%cs = 0x001b<br></blockquote><blockquote type="cite">%ds = 0x0023<br></blockquote><blockquote type="cite">%ss = 0x0023<br></blockquote><blockquote type="cite">%es = 0x0023<br></blockquote><blockquote type="cite">%fs = 0x003b<br></blockquote><blockquote type="cite">%gs = 0x0000<br></blockquote><blockquote type="cite">Exception on foreign stack<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Exception occurred while executing foreign code<br></blockquote><blockquote type="cite">? for help<br></blockquote><blockquote type="cite">[2068] Clozure CL kernel debugger: t<br></blockquote><blockquote type="cite">Current Thread Context Record (tcr) = 0x5cbc20<br></blockquote><blockquote type="cite">Control (C) stack area: low = 0xdb0000, high = 0xfb0000<br></blockquote><blockquote type="cite">Value (lisp) stack area: low = 0xfb0000, high = 0x0<br></blockquote><blockquote type="cite">Exception stack pointer = 0xfaf008<br></blockquote><blockquote type="cite">[2068] Clozure CL kernel debugger: b<br></blockquote><blockquote type="cite">current thread: tcr = 0x5cbc20, native thread ID = 0xde4, interrupts enabled<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">(#x010C0CD0) #x08D52435 : #<Function %INVOKE-STATIC-MEMBER #x08D52266> + 463<br></blockquote><blockquote type="cite">(#x010C0D14) #x08D794D5 : #<Function INVOKE #x08D7854E> + 3975<br></blockquote><blockquote type="cite">(#x010C0D78) #x08DD281D : #<Function IMPORT-TYPES #x08DD27CE> + 79<br></blockquote><blockquote type="cite">(#x010C0D88) #x0839E9BD : #<Function CALL-CHECK-REGS #x0839E8C6> + 247<br></blockquote><blockquote type="cite">(#x010C0DA4) #x083A8FE5 : #<Function TOPLEVEL-EVAL #x083A8CFE> + 743<br></blockquote><blockquote type="cite">(#x010C0DE8) #x083AAA35 : #<Function READ-LOOP #x083AA30E> + 1831<br></blockquote><blockquote type="cite">(#x010C0EFC) #x0839E60D : #<Function TOPLEVEL-LOOP #x0839E5C6> + 71<br></blockquote><blockquote type="cite">(#x010C0F04) #x0834222D : #<Function (:INTERNAL (TOPLEVEL-FUNCTION (LISP-DEVELOP<br></blockquote><blockquote type="cite">MENT-SYSTEM T))) #x083421CE> + 95<br></blockquote><blockquote type="cite">(#x010C0F14) #x0840FDED : #<Function (:INTERNAL MAKE-MCL-LISTENER-PROCESS) #x08$<br></blockquote><blockquote type="cite">0FBA6> + 583<br></blockquote><blockquote type="cite">(#x010C0F60) #x083484DD : #<Function RUN-PROCESS-INITIAL-FORM #x0834823E> + 671<br></blockquote><blockquote type="cite">(#x010C0FA4) #x08348E7D : #<Function (:INTERNAL (%PROCESS-PRESET-INTERNAL (PROCE<br></blockquote><blockquote type="cite">SS))) #x08348D2E> + 335<br></blockquote><blockquote type="cite">(#x010C0FCC) #x083317A5 : #<Function (:INTERNAL THREAD-MAKE-STARTUP-FUNCTION) #x<br></blockquote><blockquote type="cite">0833168E> + 279<br></blockquote><blockquote type="cite">[2068] Clozure CL kernel debugger:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Note that I can get RDNZL to work fine using CLISP 2.48 on this same machine.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">I believe part of the problem with CCL is that Edi's C++ code will throw a C++ exception under certain conditions (though I can't figure out why the above call to %invoke-static-member is causing an exception). Other Lisp's seem to handle this without going into the kernel debugger. For example with Clisp 2.48 running on the same machine<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">RDNZL[36]> (property "System.Reflection.Assembly" "FullName")<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">*** - .NET error (System.Exception): Static property not found:<br></blockquote><blockquote type="cite"> System.Reflection.Assembly->FullName<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Trying to call property with the same arguments in CCL bumps me into the kernel debugger. Again, I am not 100% convinced this is the problem, but I am not sure how to interpret the output from the debugger and come up with a better hypothesis of what is happening.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Best regards,<br></blockquote><blockquote type="cite">John Miller<br></blockquote><blockquote type="cite">_______________________________________________<br></blockquote><blockquote type="cite">Openmcl-devel mailing list<br></blockquote><blockquote type="cite"><a href="mailto:Openmcl-devel@clozure.com">Openmcl-devel@clozure.com</a><br></blockquote><blockquote type="cite"><a href="http://clozure.com/mailman/listinfo/openmcl-devel">http://clozure.com/mailman/listinfo/openmcl-devel</a><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><br></blockquote></div></blockquote></div><br></div></body></html>