<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body text="#000000" bgcolor="#ffffff">
R. Matthew Emerson wrote:
<blockquote type="cite" cite="mid:FE4E89A0-C806-4036-B353-B13570B19755@clozure.com"><br>
<div>
<div>On Oct 16, 2009, at 5:28 PM, John Miller wrote:</div>
<br class="Apple-interchange-newline">
<blockquote type="cite">
<div style="">
<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 size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span">(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 size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span">(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 size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"><br>
</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span">(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 style="white-space: pre;" class="Apple-tab-span"><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> </span></font></span><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span">(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>
</blockquote>
<div><br>
</div>
<div>It seems to me that you're stack-allocating the array of
pointers correctly.</div>
</div>
</blockquote>
Agreed. That makes me wonder what BOX* does, whether it's doing it
right, and whether it's the right thing to do here. I assume that
we're trying to call the second method listed at:<br>
<br>
<a href="http://msdn.microsoft.com/en-us/library/system.reflection.assembly.gettype.aspx" class="moz-txt-link-rfc2396E"><http://msdn.microsoft.com/en-us/library/system.reflection.assembly.gettype.aspx></a><br>
<br>
- the one that takes a String argument - and that BOX* of a lisp string
returns a pointer to a .NET String. Is this assumption correct, and if
so, are we sure that it works (e.g., can we do something like return a
lisp string from that .NET String, or otherwise test that) ? This
might turn out to be a dead end, but if we believe that we're passing
the array of pointers correctly one of the next things to look at would
seem to be the contents of that array ...<br>
<br>
<br>
<blockquote type="cite" cite="mid:FE4E89A0-C806-4036-B353-B13570B19755@clozure.com">
<div>
<div><br>
</div>
<div>I would try running the lisp under gdb. Load the shared library
that contains </div>
<div>#_invokeInstanceMember, and then set a gdb breakpoint on it.
Then evaluate (test-invoke-3), and see if the arguments provided from
lisp look right.</div>
<div><br>
</div>
<div>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.)</div>
</div>
</blockquote>
[...]<br>
<br>
I'm fairly sure that the library that John's trying to call into is
written in "Managed C++"; if so, tools like GDB may have trouble making
sense out any symbolic information that's available (MS compilers
generate debugging info that's in an undocumented proprietary format).
I don't know for sure; GDB might be able to at least find
#_invokeInstanceMember, but things might get weird quickly. (Weirder
than usual, I mean.)<br>
<br>
<br>
<br>
<blockquote type="cite" cite="mid:FE4E89A0-C806-4036-B353-B13570B19755@clozure.com">
<div>
<div><br>
</div>
<div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span">#include
<stdio.h></span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"><br>
</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span">void testing(char
*name, void *target, int nargs, void *args[])</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span">{</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> int i;</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"><br>
</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> fprintf(stderr,
"name = %s\n", name);</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> fprintf(stderr,
"target = %p\n", target);</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> fprintf(stderr,
"nargs = %d\n", nargs);</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"><br>
</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> for (i = 0; i <
nargs; i++)</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> fprintf(stderr,
"args[%d] = %p\n", i, args[i]);</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span">}</span></font></div>
<div><br>
</div>
</div>
<div>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.</div>
<div><br>
</div>
<div>With that in hand:</div>
<div><br>
</div>
<div>? (open-shared-library "ffi.dylib")</div>
<div>#<SHLIB ffi.dylib #x300041594C2D></div>
<div><br>
</div>
<div>Now:</div>
<div><br>
</div>
<div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span">(defun testing ()</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> (rlet ((args
(:array :address 3)))</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> (setf (paref
args (:array :address) 0) (%int-to-ptr 9)</span></font></div>
<div><span style="white-space: pre;" class="Apple-tab-span"><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> </span></font></span><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> (paref args
(:array :address) 1) (%int-to-ptr 99)</span></font></div>
<div><span style="white-space: pre;" class="Apple-tab-span"><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> </span></font></span><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> (paref args
(:array :address) 2) (%int-to-ptr 999))</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> (with-cstrs ((s
"hello"))</span></font></div>
<div><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> (external-call
"testing" :address s :address (%null-ptr) :int 3 </span></font></div>
<div><span style="white-space: pre;" class="Apple-tab-span"><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> </span></font></span><font size="2" face="Monaco" class="Apple-style-span"><span style="font-size: 10px;" class="Apple-style-span"> :address args
:void))))</span></font></div>
<div><br>
</div>
<div>? (testing)</div>
<div>
<div>name = hello</div>
<div>target = 0x0</div>
<div>nargs = 3</div>
<div>args[0] = 0x9</div>
<div>args[1] = 0x63</div>
<div>args[2] = 0x3e7</div>
<div><br>
</div>
<div>I don't know if that helps or not.</div>
<div><br>
</div>
<div><br>
</div>
</div>
</div>
</div>
<pre wrap="">
<hr width="90%" size="4">
_______________________________________________
Openmcl-devel mailing list
<a href="mailto:Openmcl-devel@clozure.com" class="moz-txt-link-abbreviated">Openmcl-devel@clozure.com</a>
<a href="http://clozure.com/mailman/listinfo/openmcl-devel" class="moz-txt-link-freetext">http://clozure.com/mailman/listinfo/openmcl-devel</a>
</pre>
</blockquote>
<br>
</body>
</html>