Hi SBCL helpers.
I think I may have tripped upon a possible problem with how SBCL deals with certain procedure parameters for foreign functions called with the stdcall calling convention in WIN32. It appears that c-strings (or char *'s) may not be passed correctly (or I am doing something wrong). Here is an example with C++ code and lisp. Note that I build a DLL using the C++ compiler, but this is just simple C code. I have built this dll with both MSVC and Eclipse (with some gcc-specific changes) on Windows.
*********** The C++ code ************************
typedef struct simple_s
{
int (__stdcall* simple)( int in_1);
char (__stdcall * simple_1)( char * in_string, int * strlen );
char (__stdcall * simple_2)( char * in_string );
} simple_struct;
int __stdcall simple( int in_1)
{
return in_1 + 10;
}
__declspec(dllexport) char __stdcall simple_1( char * in_string , int * the_strlen)
{
char c;
printf( "Hello\n" );
c = in_string[0];
*the_strlen = strlen( in_string );
return c;
//return 'A';
}
/// this one does not work!!
__declspec(dllexport) char __stdcall simple_2( char * in_string )
{
char c;
printf( "Hello\n" );
c = in_string[0];
return c;
}
__declspec(dllexport) simple_struct s =
{
&simple,
&simple_1,
&simple_2
};
__declspec(dllexport) int __stdcall GetSimpleStruct( simple_struct ** the_out_struct_ptr )
{
*the_out_struct_ptr = &s;
return 0;
}
**************** The Lisp Interaction *************************
(sb-alien:load-shared-object
"C:/Documents and Settings/John Whittaker/My Documents/Visual Studio 2005/Projects/simple_dll/debug/simple_dll.dll")
#P"C:\\Documents and Settings\\John Whittaker\\My Documents\\Visual Studio 2005\\Projects\\simple_dll\\debug\\simple_dll.dll"
CL-USER> (sb-alien:define-alien-type simple-struct
(sb-alien:struct simple-struct
(simple (* (sb-alien:function int int)))
(simple_1(* (sb-alien:function char (* char ) (* int))))
(simple_2 (* (sb-alien:function char (* char))))))
SIMPLE-STRUCT
CL-USER> (setf me-len (make-alien int))
; in: LAMBDA NIL
; SETF
; ==>
; (SETQ ME-LEN (MAKE-ALIEN INT))
;
; caught WARNING:
; undefined variable: ME-LEN
;
; caught WARNING:
; This variable is undefined:
; ME-LEN
;
; compilation unit finished
; caught 2 WARNING conditions
#<SB-ALIEN-INTERNALS:ALIEN-VALUE :SAP #X003D71A8 :TYPE (* (SIGNED 32))>
#<SB-ALIEN-INTERNALS:ALIEN-VALUE :SAP #X003D71A8 :TYPE (* (SIGNED 32))>
CL-USER> (sb-alien:define-alien-routine ("simple_2" simple-2 )
char
(the-in-string (* char)))
STYLE-WARNING: redefining SIMPLE-2 in DEFUN
SIMPLE-2
CL-USER>
; No value
CL-USER>
; No value
CL-USER> (sb-alien:define-alien-routine ("simple_1" simple-1 )
char
(the-in-string c-string) (the-out-strlen (* int)))
STYLE-WARNING: redefining SIMPLE-1 in DEFUN
SIMPLE-1
CL-USER> (simple-1 "hello there" (addr (deref me-len)))
104
CL-USER> (char-int #\h)
104
CL-USER> (deref me-len)
11
CL-USER> (sb-alien:define-alien-routine ("simple_2" simple-2 )
char
(the-in-string c-string))
STYLE-WARNING: redefining SIMPLE-2 in DEFUN
SIMPLE-2
CL-USER> (simple-2 "hello")
182057064 <<<<<----------- What is this?????????????????
CL-USER>
Is there something I am doing wrong in the interface definition for the single parameter function? I seem to get the same results whether I call the functions directly or through the function table. (I'm trying to ultimately get JFLI working with SBCL and the JNI interface is a large function table).
Thanks for any help you could provide!!
BTW: I love the foreign function interface of SBCL. I have tried to do the same JFLI work with clisp and have thrown it over for SBCL now that I see SBCL runs (pretty well) on Windows. The SBCL FFI is SOOOOO MUCH easier to understand even though it could be further documented.
John Whittaker
|