<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Oct 16, 2009, at 11:54 PM, Gary Byers wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">
<div bgcolor="#ffffff" text="#000000">
R. Matthew Emerson wrote:
<blockquote cite="mid:FE4E89A0-C806-4036-B353-B13570B19755@clozure.com" type="cite"><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 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>
  </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 class="moz-txt-link-rfc2396E" href="http://msdn.microsoft.com/en-us/library/system.reflection.assembly.gettype.aspx"><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></div></blockquote><div><br></div><div>You are right, Gary.  (box* <String>) turns into a call to</div><div><br></div><div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">(defun %make-dot-net-container-from-string (s)</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">  (ccl::with-native-utf-16-cstr (us s)</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">    (#_makeDotNetContainerFromString us)))</span></font></div><div><br></div><div>There is another function</div><div><br></div><div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">(defun get-object-as-string (container)</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">  "Get a string representation of the object denoted by CONTAINER.</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">Uses 'ToString' internally."</span></font></div><div><div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">(let ((object0 (pointer container)))</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">  (ccl:rlet ((temp1 (:* t)))</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">    (%get-dot-net-container-object-as-string object0 temp1)</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">    (ccl::%get-native-utf-16-cstring temp1)))</span></font></div><div><br></div><div>The (pointer container) function call is expecting container to be a lisp structure which encapsulates the pointer to the .Net container.  If I call (box <string>) instead of (box* <string>) I get back the structure.  So, in the below code:</div><div><br></div><div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">RDNZL> (get-object-as-string (box "A string"))</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">"A string"</span></font></div><div><br></div><div>That seems to be okay.</div></div></div></div></div></div><br><blockquote type="cite"><div bgcolor="#ffffff" text="#000000">
<br>
<blockquote cite="mid:FE4E89A0-C806-4036-B353-B13570B19755@clozure.com" type="cite">
  <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></div></blockquote><div><br></div><div>Yes, the RDNZL.dll library is sort of a thin C++ wrapper on top of .Net with an even thinner C interface on top.  The C part of %invoke-instance-member looks like</div><div><br></div><div><div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">__declspec(dllexport) void* invokeInstanceMember(const __wchar_t *methodName, void *target, int nargs, void *args[]) {</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">  DotNetContainer *container = static_cast<DotNetContainer *>(target);</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">  Type ^t = container->getContainerType();</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">  Object ^o = container->getContainerObject();</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">  return InvokeMember::invokeMethod(o, t, methodName, nargs, args, static_cast<BindingFlags>(BindingFlags::Instance | BindingFlags::Public));</span></font></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">}</span></font></div></div><div><br></div><div>While the C++ declaration for InvokeMember::invokeMethodDirectly looks like</div><div><br></div><div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">void* InvokeMember::invokeMethod(Object ^o, Type ^t, const __wchar_t *methodName, int nargs, void *args[], BindingFlags bindingAttr)</span></font></div><div><br></div><div>I was a little suspicious of that bindingAttr variable, but I can invoke-instance-member as long as nargs is 0 and args is a null-ptr.  I would think the problem is with the C++ code, but it has been well tested under various other Lisp implementations in windows and works fine with those.  Most probably I am doing something wrong, but it certainly isn't obvious what at the moment.</div><div><br></div></div><div><br></div><br><blockquote type="cite"><div bgcolor="#ffffff" text="#000000">
<br>
<blockquote cite="mid:FE4E89A0-C806-4036-B353-B13570B19755@clozure.com" type="cite">
  <div>
  <div><br>
  </div>
  <div>
  <div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px; ">#include
<stdio.h></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;">void testing(char
*name, void *target, int nargs, void *args[])</span></font></div>
  <div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">{</span></font></div>
  <div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">  int i;</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;">  fprintf(stderr,
"name = %s\n", name);</span></font></div>
  <div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">  fprintf(stderr,
"target = %p\n", target);</span></font></div>
  <div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">  fprintf(stderr,
"nargs = %d\n", nargs);</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;">  for (i = 0; i <
nargs; i++)</span></font></div>
  <div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">    fprintf(stderr,
"args[%d] = %p\n", i, args[i]);</span></font></div>
  <div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">}</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 class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">(defun testing ()</span></font></div>
  <div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">  (rlet ((args
(:array :address 3)))</span></font></div>
  <div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">    (setf (paref
args (:array :address) 0) (%int-to-ptr 9)</span></font></div>
  <div><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;">  (paref args
(:array :address) 1) (%int-to-ptr 99)</span></font></div>
  <div><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;">  (paref args
(:array :address) 2) (%int-to-ptr 999))</span></font></div>
  <div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">    (with-cstrs ((s
"hello"))</span></font></div>
  <div><font class="Apple-style-span" face="Monaco" size="2"><span class="Apple-style-span" style="font-size: 10px;">      (external-call
"testing" :address s :address (%null-ptr) :int 3 </span></font></div>
  <div><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;">     :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></blockquote></div></blockquote><div><br></div><div>Thanks.  I will see if I remember how to create DLL's in Mingw and give the above a try.</div><div><br></div><br><blockquote type="cite"><div bgcolor="#ffffff" text="#000000"><blockquote cite="mid:FE4E89A0-C806-4036-B353-B13570B19755@clozure.com" type="cite"><div><div><div><div>
  </div>
  </div>
  </div>
  </div>
  <pre wrap=""><hr size="4" width="90%">
_______________________________________________
Openmcl-devel mailing list
<a class="moz-txt-link-abbreviated" href="mailto:Openmcl-devel@clozure.com">Openmcl-devel@clozure.com</a>
<a class="moz-txt-link-freetext" href="http://clozure.com/mailman/listinfo/openmcl-devel">http://clozure.com/mailman/listinfo/openmcl-devel</a>
  </pre>
</blockquote>
<br>
</div>

</blockquote></div><br></body></html>