[Openmcl-devel] RDNZL in CCL: Exception occurred while executing foreign code

R. Matthew Emerson rme at clozure.com
Sat Oct 17 03:39:32 UTC 2009


On Oct 16, 2009, at 5:28 PM, John Miller wrote:

> The problem looks to be one of passing the wrong type of argument.   
> The C function I am calling is defined as
>
> void* invokeInstanceMember(const __wchar_t *methodName, void  
> *target, int nargs, void *args[])
>
> h-to-ffi.sh interprets that to be
>
> (function ("/cygdrive/d/rdnzl-cpp-0.7.1/RDNZL/ffi-headers.h" 55)
>  "invokeInstanceMember"
>  (function
>   ((pointer (unsigned-short ())) (pointer (void ())) (int ())  
> (pointer (pointer (void ()))) )
>   (pointer (void ()))) (extern))
>
> Then, given the following definitions:
>
> (defun %invoke-instance-member (method-name type nargs args)
>   (ccl::with-native-utf-16-cstr (mn method-name)
>     (#_invokeInstanceMember mn type nargs args)))
>
> (defun test-invoke-2 ()
>   (let ((obj (make-type-from-name "System.Reflection.Assembly")))
>     (%invoke-instance-member "ToString" (pointer obj) 0 (ccl:%null- 
> ptr))))
>
> (defun test-invoke-3 ()
>   (let ((obj (make-type-from-name "System.Reflection.Assembly"))
> 	(type (box* "System.Reflection.Assembly")))
>     (ccl:rletz ((ptr (:array :address 1)))
>       (setf (ccl:paref ptr (:array :address) 0) type)
>       (%invoke-instance-member "GetType" (pointer obj) 1 ptr))))
>
> 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.
>
> 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.

It seems to me that you're stack-allocating the array of pointers  
correctly.

I would try running the lisp under gdb.  Load the shared library that  
contains
#_invokeInstanceMember, and then set a gdb breakpoint on it.  Then  
evaluate (test-invoke-3), and see if the arguments provided from lisp  
look right.

Here's a trivial example I just came up with and ran on my Mac. (I  
tried to do it on Windows, but I couldn't figure out at a quick glance  
how to build a working dll with cygwin tools.)

#include <stdio.h>

void testing(char *name, void *target, int nargs, void *args[])
{
   int i;

   fprintf(stderr, "name = %s\n", name);
   fprintf(stderr, "target = %p\n", target);
   fprintf(stderr, "nargs = %d\n", nargs);

   for (i = 0; i < nargs; i++)
     fprintf(stderr, "args[%d] = %p\n", i, args[i]);
}

Compile that as a shared library, e.g., with cc -arch x86_64 -shared  
ffi.c -o ffi.dylib or whatever the right thing is for your system.   
Sorry to hand-wave like this.

With that in hand:

? (open-shared-library "ffi.dylib")
#<SHLIB ffi.dylib #x300041594C2D>

Now:

(defun testing ()
   (rlet ((args (:array :address 3)))
     (setf (paref args (:array :address) 0) (%int-to-ptr 9)
	  (paref args (:array :address) 1) (%int-to-ptr 99)
	  (paref args (:array :address) 2) (%int-to-ptr 999))
     (with-cstrs ((s "hello"))
       (external-call "testing" :address s :address (%null-ptr) :int 3
		     :address args :void))))

? (testing)
name = hello
target = 0x0
nargs = 3
args[0] = 0x9
args[1] = 0x63
args[2] = 0x3e7

I don't know if that helps or not.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.clozure.com/pipermail/openmcl-devel/attachments/20091016/b9f96bdb/attachment.html>


More information about the Openmcl-devel mailing list