[Openmcl-devel] RDNZL in CCL: Exception occurred while executing foreign code
John Miller
millejoh at mac.com
Sun Oct 18 06:42:36 PDT 2009
Well, I may not be too savvy to use gdb or WinDBG, but I can download
Visual Studio C++ Express and write lots of fprintf statements. The
array of pointers is not the problem. In fact argument passing is not
the problem. The problem is that the method I am calling in the code
below ("GetType") is not defined for the .Net class System.Type, which
is what is returned when I call make-type-from-name.
In the managed C++ code when that happens it tries to throw an
exception via the following code:
String ^msg = String::Concat(
(int)(BindingFlags::Static &
bindingAttr) ? "Static method not found: " : "Instance method not
found: ",
type->FullName,
"::",
gcnew String(methodName)
);
msg = String::Concat(msg, "(");
for (int i = 0; i < argTypes->Length; i++) {
if (i)
msg = String::Concat(msg, ",");
msg = String::Concat(msg, argTypes[i]->FullName);
}
msg = String::Concat(msg, ")");
fprintf(stderr,"%s\n",msg);
throw gcnew Exception (msg);
I can see the error message printed by the fprintf statement, but when
it tries to do "throw gcnew Exception(msg);" Why is throw causing a
machine level exception to occur?
Thanks,
John
On Oct 17, 2009, at 8:33 AM, John Miller wrote:
>
> On Oct 16, 2009, at 10:39 PM, R. Matthew Emerson wrote:
>
>>
>> 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.
>>
>>
>
> FYI, the incantation for creating a dll in mingw (installed as part
> of cygwin) is (wait for it):
>
> gcc -mno-cygwin -shared test.c -o test.dll
>
> And some more FYI: I get the exact same results as you with the
> testing function defined above. The thought of using GDB (Gary also
> mention WinDBG) is making me break out in a bit of a cold sweat, but
> I will try and see if I can make that work and get a little more
> info...
>
> Thanks again,
> John
>
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.clozure.com/pipermail/openmcl-devel/attachments/20091018/39c422a4/attachment.htm>
More information about the Openmcl-devel
mailing list