Gary King -- thank you!<br><br>Gary Byers --thank you for the pointers and the lucid explanation. <br><br>All -- words of warning about SWIG and Common Lisp, as of March 2011:<br><br>The reason for my question to begin with was that I was puzzled. I was puzzled over why the binding generator (SWIG) could possibly be generating bad code. I turns out that I was fooled by early small successes with SWIG. I was fooled into thinking that the SWIG code generator for CFFI was producing correct code.<br>
<br>In fact after much pounding on it, I realize that SWIG's CFFI module is incomplete and alpha quality at that.<br><br>I've since then corresponded with the current maintainer for SWIG (William Fulton) and he confirmed that the CFFI module for SWIG hasn't been touched in 5-6 years, and that it was never very good to begin with, so there's both bitrot and a partial implementation to begin with to account for.<br>
<br>That said, the cffi.cxx module seems reasonable place to start, and I'm willing to enhance it. It clearly doesn't handle overloaded C or C++ methods --those differing only in the number of arguments. It doesn't seem like it would be too bad to flesh out the capability, but if anyone knows of a functional LISP-C++ bridge, I'd certainly be happy not to reinvent the wheel(!)<br>
<br>So do let me know if you have an alternative for doing Lisp to C++ bindings.<br><br>Once issue that I would appreciate commentary on, with regards to binding C++ and C functions with different numbers of arguments: are generic functions expensive? That seemed to be the motivation for not allow overriding on "ordinary" functions. Can the compilers not optimize generic dispatch well? <br>
<br>As far as how to handle functions of the same name but different arity, the simplest idea (bordering on a hack) would be to use the C++ mangled names directly, and let the user define aliases using symbols of their choice. This would be clean and clear, if a bit illegible at first. The next easiest thing to do when doing Lisp bindings for two C functions would be to use defgeneric, which is apparently meant to dispatch to different methods based on different numbers and values of arguments. The problem is real for me, in my C++ code base, as a small example, there are two C functions<br>
<br>char *wchar2ascii(wchar_t *); <br>char *wchar2ascii(wchar_t *, unsigned len); <br>
<br>Currently SWIG's CFFI module generate this two functions in Lisp:<br><br>(cffi:defcfun ("_wrap_wchar2ascii__SWIG_0" wchar2ascii) :string<br> (arg0 :pointer))<br><br>(cl:export 'wchar2ascii)<br><br>; and<br>
<br>(cffi:defcfun ("_wrap_wchar2ascii__SWIG_1" wchar2ascii) :string<br> (arg0 :pointer)<br> (len :unsigned-int))<br><br>(cl:export 'wchar2ascii)<br><br>Notice that the same symbol is used for both. Thus the problem.<br>
<br>Anyway, I welcome advice on how to proceed. (Thanks in advance.)<br><br>As a side comment, in accordance with that often repeated Greenspun remark about big projects 'reinventing lisp', I do note that SWIG is internally a half-done version of Lisp. Quite amusing as I look through the internals, to see dynamic typing bolted atop C like that.<br>
<br>Best,<br>Jason<br><br><br><div class="gmail_quote">On Sat, Apr 2, 2011 at 4:25 AM, Gary Byers <span dir="ltr"><<a href="mailto:gb@clozure.com" target="_blank">gb@clozure.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<<a href="http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html" target="_blank">http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html</a>><br>
<br>
is a chapter from Peter Seibel's book "Practical Common Lisp"; hardcopy of<br>
that book is available from (among other places) Amazon:<br>
<br>
<<a href="http://www.amazon.com/Practical-Common-Lisp-Peter-Seibel/dp/1590592395" target="_blank">http://www.amazon.com/Practical-Common-Lisp-Peter-Seibel/dp/1590592395</a>><br>
<br>
If you're just learning CL and CLOS, you'll probably find the answer<br>
to your question easier to understand if you read that chapter or something<br>
of similar scope. A short version of that answer (without the background<br>
information that a tutorial would provide) is:<br>
<br>
1) CL defines a subtype of FUNCTION - called GENERIC-FUNCTION.<br>
2) A GENERIC-FUNCTION can have one or more METHODs associated with it.<br>
3) A METHOD (in the simplest case, it can be more complicated than this)<br>
associates a set of argument types with a function. The argument types<br>
(classes, mostly) are often called the method's specializers.<br>
All of the methods defined on a generic function have to accept (roughly)<br>
similar arguments, and only required arguments can be specialized.<br>
4) When called with an appropriate number of arguments, a GENERIC-FUNCTION<br>
uses the types of the specializable arguments (mostly) to select a set<br>
of one or more of the generic function's methods (a set of "applicable<br>
methods") and calls them. (What happens when there's more or less than<br>
one applicable method is interesting; read a tutorial.) The GENERIC-FUNCTION<br>
doesn't implement any otherwise interesting behavior; its applicable methods<br>
do. Methods can be added to (and removed from) a generic function at runtime<br>
(and certainly during development); there are other ways of doing this,<br>
but the most common way of defining a method and adding it to a generic function<br>
is via the DEFMETHOD macro.<br>
5) A non-generic function can't be incrementally augmented in this way. The<br>
function named CL:+ is usually not generic, so there's no easy way to extend<br>
it (to, for instance, allow it to be extended to perform addition on a user-defined<br>
POLYNOMIAL type.) CL:+ is often used as a canonical example of a non-generic<br>
function that could be implemented as a generic function. There are performance<br>
and other tradeoffs involved, and (most ? all ?) CL implementations define<br>
CL:+ as a non-generic function (but it's perfectly legal for an implementation<br>
to define it generically.)<br>
6) DEFMETHOD defines a named METHOD and adds it to the corresponding generic function.<br>
What that means is that, when it's executed:<br>
<br>
(defmethod name ...)<br>
<br>
looks up the global function definition of NAME. If there's no global definition -<br>
if (FBOUNDP NAME) is false - a new GENERIC-FUNCTION is installed as NAME's<br>
global function definition and the method is added to that generic function.<br>
<br>
If the global function definition of NAME is already a generic function, the<br>
method is added to its set of methods (possibly replacing any previously-defined<br>
method with the same set of specializers. And qualifiers, but we're ignoring<br>
them for now.)<br>
<br>
If neither of these conditions hold - NAME has a global function definition but<br>
that definition isn't a GENERIC-FUNCTION - then the expansion of DEFMETHOD<br>
must signal an error. (There'd be no way to add the method to a non-generic<br>
function.)<br>
<br>
This error is what you're seeing: CL:PRINT is defined as a non-generic function,<br>
and there's no way for the code generated by DEFMETHOD to associate a METHOD with<br>
that non-generic function. (The standard way of specializing the printer's<br>
behavior is to define methods on #'CL:PRINT-OBJECT, which is required to be a<br>
GENERIC-FUNCTION. CL:PRINT and other functions that ... print things ... call<br>
PRINT-OBJECT to handle the details of printing specific types of objects.)<br>
<br>
Some of the above is oversimplified to the point that it may not be entirely<br>
accurate, but it's hopefully pretty close, and it's already a lot longer than<br>
I'd intended it to be.<div><br>
<br>
On Sat, 2 Apr 2011, Jason E. Aten wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
I'm trying to define a print method for my class, and I'm getting "Error:<br>
The function PRINT is defined as something other than a generic function."<br>
<br>
Below shows the two commands that when issues, reproduce this on Linux<br>
x86_64.? What should I try instead?<br>
<br>
Apologies if this is obvious. I'm new to CLOS, and these classes are auto-<br>
generated by SWIG as wrappers for C++ classes.<br>
<br>
Jason<br><br>
</blockquote></div></blockquote></div>