Hi,
I'm trying to call functions written in scheme from C. I saw the server.scm and client.c as mentioned in docs, but I could not quite understand what it was doing. I also could not successfully link the application. Where can I find documentation for the ___setup function and the steps for compiling such a program?
TIA.
Aditya.
Afficher les réponses par date
On 13-Jun-09, at 5:15 AM, Aditya Godbole wrote:
Hi,
I'm trying to call functions written in scheme from C. I saw the server.scm and client.c as mentioned in docs, but I could not quite understand what it was doing. I also could not successfully link the application. Where can I find documentation for the ___setup function and the steps for compiling such a program?
TIA.
Aditya.
I've tried to come up with a simpler example than server.scm/client.c to explain how to write the C and Scheme code. The files are: "main-c- app.c" (the main program written in C) and "scmlib.scm" (the library of Scheme procedures you want to call from C). To keep things simple, scmlib.scm only defines the "hello" procedure which displays a message (a string passed from C to Scheme) and returns the length of the string.
The files are attached below and the top of main-c-app.c shows how to build the executable program (in a nutshell: use the -link option of gsc, and pass -D___LIBRARY and -lgambc to the C compiler when compiling the C code generated by gsc).
These are the fields of a ___setup_params_struct structure that can be set (note that calling ___setup_params_reset will assign reasonable default settings):
int version; /* must be equal to ___VERSION */ ___UCS_2STRING *argv; /* argv as UCS-2 strings */ unsigned long min_heap; /* min heap size */ unsigned long max_heap; /* max heap size */ int live_percent; /* live percentage (50 gives 50%) */ int standard_level; /* 5 gives R5RS */ int debug_settings; /* combination of ___DEBUG_SETTINGS_... values */ int file_settings; /* default file I/O settings (char- encoding, eol-encoding, ...) */ int terminal_settings; /* default terminal I/O settings */ int stdio_settings; /* default stdio I/O settings */ ___mod_or_lnk (*linker) ___P((___global_state_struct*),()); /* linker C function */
/* the following settings are not documented */ long (*gc_hook) ___P((long avail, long live),()); void (*display_error) ___P((char **msgs),()); void (*fatal_error) ___P((char **msgs),()); ___UCS_2STRING gambcdir; ___UCS_2STRING *gambcdir_map; ___UCS_2STRING remote_dbg_addr; ___UCS_2STRING rpc_server_addr;
Marc
----------------------------------------------------------------------- ;;; File: "scmlib.scm"
(c-define (hello str) (char-string) int "hello" "extern" (println "hello " str) (string-length str)) ----------------------------------------------------------------------- /* File: "main-c-app.c" */
/* % gsc -link scmlib.scm % gcc main-c-app.c -D___LIBRARY scmlib.c scmlib_.c -lgambc % ./a.out hello montreal returned 8 hello world returned 5 */
#define ___VERSION 404004 #include "gambit.h"
#define SCHEME_LIB_LINKER ____20_scmlib__
___BEGIN_C_LINKAGE extern ___mod_or_lnk SCHEME_LIB_LINKER (___global_state_struct*); ___END_C_LINKAGE
#include <stdio.h>
extern int hello( char *str ); /* defined in scmlib.scm */
int main( int argc, char **argv ) { ___setup_params_struct setup_params;
___setup_params_reset( &setup_params );
setup_params.version = ___VERSION; setup_params.linker = SCHEME_LIB_LINKER;
___setup( &setup_params ); /* setup Scheme library */
printf( "returned %d\n", hello( "montreal" ) ); printf( "returned %d\n", hello( "world" ) );
___cleanup(); /* cleanup Scheme library */
return 0; } -----------------------------------------------------------------------
On Sat, Jun 13, 2009 at 5:01 PM, Marc Feeleyfeeley@iro.umontreal.ca wrote:
I've tried to come up with a simpler example than server.scm/client.c to explain how to write the C and Scheme code.
Thanks, I've got it working with a few minor modifications like the -I and -L flags to gcc. I still have a couple of questions (and a suggestion), mentioned below.
<snip>
int stdio_settings; /* default stdio I/O settings */ ___mod_or_lnk (*linker) ___P((___global_state_struct*),()); /* linker C function */
Do we need to provide this linker function because the entry point of the executable is generated from our code, instead of the code in gambit.h?
Maybe it would be better (easier for the programmer) if the following were done:
gambit.h: ------------------------------------------------------------------------ #ifndef ___SCHEME_LIB_LINKER #define ___SCHEME_LIB_LINKER NULL #endif
#define ___setup_params_reset(x) _setup_params_reset((x),___SCHEME_LIB_LINKER) -----------------------------------------------------------------------
The _setup_params_reset sets the value of linker if ___SCHEME_LIB_LINKER is not NULL.
scmlib_.h (generated by gsc along with scmlib.c and scmlib_.c): --------------------------------------------------------------------------- #ifndef ___SCHEME_LIB_LINKER #define ___SCHEME_LIB_LINKER ___20_scmlib_ #endif
___BEGIN_C_LINKAGE extern ___mod_or_lnk ___SCHEME_LIB_LINKER (___global_state_struct*); ___END_C_LINKAGE --------------------------------------------------------------------------- Using the above method, the end programmer would only have to include scmlib_.h, instead of being bothered with the all the #defines. If required he would still be able to set the ___SCHEME_LIB_LINKER manually (maybe a macro ___setup_linker could be provided for that). The above scheme will also maintain compatibility with earlier code (unless someone has explicitly defined ___SCHEME_LIB_LINKER, in which case another obscure name could be chosen).
The C code would then look like: --------------------------------------------------------------------------- #define ___VERSION 404004 #include "gambit.h" #include "scmlib_.h" #include <stdio.h>
/* The definition below could also go into scmlib_.h */ extern int hello( char *str ); /* defined in scmlib.scm */
int main( int argc, char **argv ) { ___setup_params_struct setup_params;
___setup_params_reset( &setup_params );
/* This could also be engulfed by the wrapper macro suggested above */ setup_params.version = ___VERSION;
___setup( &setup_params ); /* setup Scheme library */
printf( "returned %d\n", hello( "montreal" ) ); printf( "returned %d\n", hello( "world" ) );
___cleanup(); /* cleanup Scheme library */
return 0; } --------------------------------------------------------------------------------
#define ___VERSION 404004
Why is this definition required? Is it just a form of a check to alert against using different versions?
-aditya
On 13-Jun-09, at 4:48 PM, Aditya Godbole wrote:
On Sat, Jun 13, 2009 at 5:01 PM, Marc Feeleyfeeley@iro.umontreal.ca wrote:
I've tried to come up with a simpler example than server.scm/ client.c to explain how to write the C and Scheme code.
Thanks, I've got it working with a few minor modifications like the -I and -L flags to gcc. I still have a couple of questions (and a suggestion), mentioned below.
<snip> > int stdio_settings; /* default stdio I/O settings */ > ___mod_or_lnk (*linker) ___P((___global_state_struct*),()); /* > linker C > function */ >
Do we need to provide this linker function because the entry point of the executable is generated from our code, instead of the code in gambit.h?
Yes. The logic in gambit.h will define a C main function when the link file (i.e. the foo_.c file produced by gsc -link foo.scm) is compiled without the -D___LIBRARY flag. That main will indirectly call ___setup to get the program running.
So when the -D___LIBRARY flag is used, the call to ___setup (and the "main" function) must appear elsewhere.
Maybe it would be better (easier for the programmer) if the following were done: ...
Thanks for the suggestion. This however doesn't seem to save much work and it introduces an extra file (scmlib_.h), which makes the whole process a bit more cumbersome. Moreover Gambit will soon have a way to run independent instances of Gambit in the same process (possibly in different threads), and your suggestion would not work in that context.
#define ___VERSION 404004
Why is this definition required? Is it just a form of a check to alert against using different versions?
Yes it is a consistency check that the client which is using Gambit (i.e. the "C application") is using the API for the required version. The version information also allows gambit.h to chose to include the correct gambit.h by a cascading mechanism (this is not used much, and you have to set it up manually). If the v4.4.4 gambit.h is in your include path, and you do a #define ___VERSION 404003 before the #include "gambit.h", then the file "gambit-not404004.h" will be included. If you have renamed the v4.4.3 gambit.h to gambit- not404004.h then you will be able to compile code with the v4.4.4 and v4.4.3 Gambit compilers.
Marc
On Sat, 2009-06-13 at 07:31 -0400, Marc Feeley wrote:
% gsc -link scmlib.scm % gcc main-c-app.c -D___LIBRARY scmlib.c scmlib_.c -lgambc % ./a.out hello montreal returned 8 hello world returned 5
*/
Marc:
Once again examples of mixing C and Scheme code on this list contain incorrect gcc compiler options. You will quite possibly get incorrect results in the executable if you don't include -fwrapv, -fno-strict-aliasing, -mieee (on x86), etc., etc., all those options that you work so hard to get right in gsc-cc-o.bat.
I recommend that you put together shell-scripts:
gsc-compile-c-to-o gsc-link-c-to-scheme
that will have the correct options.
This is bug 103.
Brad
On 13-Jun-09, at 6:05 PM, Bradley Lucier wrote:
On Sat, 2009-06-13 at 07:31 -0400, Marc Feeley wrote:
% gsc -link scmlib.scm % gcc main-c-app.c -D___LIBRARY scmlib.c scmlib_.c -lgambc % ./a.out hello montreal returned 8 hello world returned 5 */
Marc:
Once again examples of mixing C and Scheme code on this list contain incorrect gcc compiler options. You will quite possibly get incorrect results in the executable if you don't include -fwrapv, -fno-strict-aliasing, -mieee (on x86), etc., etc., all those options that you work so hard to get right in gsc-cc-o.bat.
I recommend that you put together shell-scripts:
gsc-compile-c-to-o gsc-link-c-to-scheme
that will have the correct options.
This is bug 103.
Brad
Thanks for the suggestion. The problem is that there are so many different ways that the C code generated by gsc can be used (creating a .o file, creating an executable, creating a plugin, etc). Depending on the case you may want some unusual C compiler options, like selecting the calling convention, position independent code, profiling, etc.
So it doesn't seem like the right solution to package all of these decisions in a single script.
What is the right abstraction?
Marc
So it doesn't seem like the right solution to package all of these decisions in a single script.
What is the right abstraction?
I guess that the right abstraction is - conservative: it always works - end user-oriented: it should work out of the box for those who know nothing and don't want to know more. A few others will tweak it manually. Most people do *not* need unusual (sic) compiler options, or to select the calling convention.
In short: It's better to make it work out of the box for 90% of the users than to make something highly (and with difficulty) configurable for the rest 10%.
Package the "stupid" scripts, and let other users do everything manually as before…
P!
On Jun 14, 2009, at 11:32 PM, Adrien Piérard wrote:
So it doesn't seem like the right solution to package all of these decisions in a single script.
What is the right abstraction?
I guess that the right abstraction is
- conservative: it always works
- end user-oriented: it should work out of the box for those who know
nothing and don't want to know more. A few others will tweak it manually. Most people do *not* need unusual (sic) compiler options, or to select the calling convention.
For some reason I didn't get Marc's reply (I see it on the list archive, though).
Anyone building applications or dynamically-loadable libraries, or calling scheme from C, or ... will have to know *something* beyond
gsc file gsi file
Perhaps the following flags from the makefiles could be exported somehow (have a script that a user can run (in their .bashrc or .cshrc file?) that will add them to one's environment, as GSC_FLAGS_OBJ or something), or perhaps they could just be used in the examples on this list or in the documentation as symbolic variables.
On my PowerPC Mac I have:
FLAGS_OBJ = -no-cpp-precomp -Wall -W -Wno-unused -O1 -fno-math- errno -fschedule-insns2 -O1 -fno-math-errno -fschedule-insns2 -fno- trapping-math -fno-strict-aliasing -fwrapv -fomit-frame-pointer -fPIC -fno-common FLAGS_DYN = -no-cpp-precomp -Wall -W -Wno-unused -O1 -fno-math- errno -fschedule-insns2 -O1 -fno-math-errno -fschedule-insns2 -fno- trapping-math -fno-strict-aliasing -fwrapv -fomit-frame-pointer -fPIC -fno-common -bundle -flat_namespace -undefined suppress FLAGS_LIB = -dynamiclib -flat_namespace -undefined suppress FLAGS_EXE = DEFS = -DHAVE_CONFIG_H LIBS =
On my Linux box I have
FLAGS_OBJ = -Wno-unused -O1 -fno-math-errno -fschedule-insns2 -fno- trapping-math -fno-strict-aliasing -fwrapv -fomit-frame-pointer -fno- move-loop-invariants -fPIC -fno-common -mieee-fp FLAGS_DYN = -Wno-unused -O1 -fno-math-errno -fschedule-insns2 - fno-trapping-math -fno-strict-aliasing -fwrapv -fomit-frame-pointer - fno-move-loop-invariants -fPIC -fno-common -mieee-fp -rdynamic -shared FLAGS_LIB = -rdynamic -shared FLAGS_EXE = -rdynamic DEFS = -DHAVE_CONFIG_H LIBS = -lutil -ldl -lm
Quite a few of these are required either for correctness of the compiled code (-fno-math-errno -fno-trapping-math -fno-strict- aliasing -fwrapv -mieee-fp -fPIC), speed of the compiled code (-O1 - fschedule-insns2 -fomit-frame-pointer), runtime of gcc when compiling Gambit-generated code (-fno-move-loop-invariants) or for other reasons that I'm not sure about.
So, perhaps this isn't a bad idea. These options vary from OS to OS, they're chosen at configure time, perhaps there should be a standard way that a Gambit user can access them.
Brad
On 14-Jun-09, at 11:58 PM, Bradley Lucier wrote:
On Jun 14, 2009, at 11:32 PM, Adrien Piérard wrote:
So it doesn't seem like the right solution to package all of these decisions in a single script.
What is the right abstraction?
I guess that the right abstraction is
- conservative: it always works
- end user-oriented: it should work out of the box for those who know
nothing and don't want to know more. A few others will tweak it manually. Most people do *not* need unusual (sic) compiler options, or to select the calling convention.
For some reason I didn't get Marc's reply (I see it on the list archive, though).
Anyone building applications or dynamically-loadable libraries, or calling scheme from C, or ... will have to know *something* beyond
gsc file gsi file
Perhaps the following flags from the makefiles could be exported somehow (have a script that a user can run (in their .bashrc or .cshrc file?) that will add them to one's environment, as GSC_FLAGS_OBJ or something), or perhaps they could just be used in the examples on this list or in the documentation as symbolic variables.
Here's the idea I will implement. Let me know ASAP if you have suggestions.
The gsc compiler will have some new options. Currently there is:
gsc -c foo.scm generate foo.c from foo.scm gsc -link foo.scm generate foo.c and foo_.c from foo.scm gsc -dynamic foo.scm generate foo.o1 from foo.scm
I will add two new options:
gsc -obj foo.scm generate foo.o (or foo.obj) from foo.scm gsc -exe foo.scm generate foo (or foo.exe) from foo.scm
As with the above -c, -link and -dynamic options the name of the file can be chosen with the -o option and C compiler and linker options can be added with the options -cc-options and -ld-options .
The C compiler and linker knowledge will be encapsulated in the gsc- cc.bat script (renamed from gsc-cc-o.bat), which will perform the appropriate action(s) depending on command line arguments and environment variables. With no command line argument the gsc-cc.bat script will dump its knowledge to stdout. The format will be along the lines of:
GSC_CC_COMMAND="gcc -O1 -fwrapv ..." GSC_LINK_COMMAND="ld ..."
That way the user can use this knowledge in his own build procedure, as in
% `gsc-cc.bat` make
There will also be an environment variable GSC_CC_DEBUG which dumps to stdout a trace of the command(s) that the script is executing. So you can do:
% GSC_CC_DEBUG=1 gsc foo.scm
or
% GSC_CC_DEBUG=1 make
One remaining issue... what should be the default gsc option? Currently it is -dynamic, but for consistency with other compilers, and in particular C compilers, perhaps the -exe option should be the default. That way you can do:
% gsc foo.scm % ./foo
and to get a dynamically loadable library you will have to do:
% gsc -dynamic foo.scm % gsi foo
Marc
On Jun 15, 2009, at 9:33 AM, Marc Feeley wrote:
One remaining issue... what should be the default gsc option? Currently it is -dynamic, but for consistency with other compilers, and in particular C compilers, perhaps the -exe option should be the default. That way you can do:
% gsc foo.scm % ./foo
and to get a dynamically loadable library you will have to do:
% gsc -dynamic foo.scm % gsi foo
I think with dynamic languages like Scheme and Lisp with a REPL and a large runtime, the default should remain -dynamic.
Brad
Bradley Lucier wrote:
On Jun 15, 2009, at 9:33 AM, Marc Feeley wrote:
One remaining issue... what should be the default gsc option? Currently it is -dynamic, but for consistency with other compilers, and in particular C compilers, perhaps the -exe option should be the default. That way you can do:
% gsc foo.scm % ./foo
and to get a dynamically loadable library you will have to do:
% gsc -dynamic foo.scm % gsi foo
I think with dynamic languages like Scheme and Lisp with a REPL and a large runtime, the default should remain -dynamic.
I would like to agree with Brad. Scheme users, especially new ones, should be encouraged to used dynamicly compiled sources, and the good way of encouraging them (or let them know it exists) is to have this as the default compilation format. :) This should encourage dynamic development, which is at the core of languages like Scheme!
Having the -exe flag will sure simplifies the standalone executable build process though! hehe Thanks Marc!
David
2009/6/15 Bradley Lucier lucier@math.purdue.edu:
On Jun 15, 2009, at 9:33 AM, Marc Feeley wrote:
One remaining issue... what should be the default gsc option? Currently
I think with dynamic languages like Scheme and Lisp with a REPL and a large runtime, the default should remain -dynamic. Brad
I was going to answer "static", but in fact, dynamic is ok.
However, as it is a long name, --exe and --dynamic are more consistent (double hyphens).
I really like this --exe idea. It would be cool too if, while doing its job, it could print each step it's following (showing each independently run command).
GHC has a neat ghc --make command, which basically does (half of) what you are going to do http://www.haskell.org/ghc/docs/latest/html/users_guide/modes.html#make-mode Can gambit too, follow dependencies the same way and build too object files when it sees a load/include and that the file is there (and that no static analysis shows this load is in fact dynamically bound to a function that returns the pi-th root of the golden ratio)
Finally, this improvement should get highlights on the website (as in "See how easy it is!")
P!
GHC has a neat ghc --make command, which basically does (half of) what you are going to do http://www.haskell.org/ghc/docs/latest/html/users_guide/modes.html#make-mode Can gambit too, follow dependencies the same way and build too object files when it sees a load/include and that the file is there (and that no static analysis shows this load is in fact dynamically bound to a function that returns the pi-th root of the golden ratio)
I wouldn't want this. It's common in Gambit for LOAD to be ambiguous, i.e. if you want your module to be compiled, you compile it; if you want it to be interpreted, you don't compile it. I switch between interpreted/compiled a good bit for individual modules for debugging, interactivity, quick development, etc.
If Gambit ever adopts a module system, we may have enough information to rationalize about the modules, and this may be possible.
2009/6/16 James Long longster@gmail.com:
I wouldn't want this. It's common in Gambit for LOAD to be ambiguous,
I meant to write a question, but forgot the mark. That's also why I added the static analysis part (as in "if you don't know, don't do it").
*Yet*, even thoung linking too early may be bad, *compiling* ahead might not (but then, I don't remember/know whether state involved during macro expansion "survives" at run time and can be used when loading another file with macros).
If Gambit ever adopts a module system, we may have enough information to rationalize about the modules, and this may be possible.
I should fork a new thread for that, but besides its newness [1] and the complete lack of documentation on the wiki, are there any drawbacks to blackhole?
P!
[1] That's a nice word I've never heard or used before today. Not quite like "novelty", right?
Here are some thoughts:
On Sun, 14 Jun 2009 17:29:36 +0300, Marc Feeley feeley@iro.umontreal.ca wrote:
Thanks for the suggestion. The problem is that there are so many different ways that the C code generated by gsc can be used (creating a .o file, creating an executable, creating a plugin, etc). Depending on the case you may want some unusual C compiler options, like selecting the calling convention, position independent code, profiling, etc.
Regardless of the diversity of use, .o files will be generated. The diversity consist in the content of the .o files and in their linking.
The content is influenced by flags: - language dependent options - machine dependent options - translation step dependent options - warning and debugging options - optimization options
The options can be: - implicit/explicit - required/optional
There are two kind of code uses: - linking - calling
The .o files are linked into modules: - executables - libraries
The calls can be inter/intra modules.
It seems that the objective is geting the linking and the calling right. Maybe a matrimonial agency is required :-)
So it doesn't seem like the right solution to package all of these decisions in a single script.
What is the right abstraction?
Scheme code and/or makefiles ?
________ Information from NOD32 ________ This message was checked by NOD32 Antivirus System for Linux Mail Servers. part000.txt - is OK http://www.eset.com
2009/6/15 Cristian Baboi cristi@ot.onrc.ro:
What is the right abstraction?
Scheme code and/or makefiles ?
Makefiles… Hum… It's quite portable, though, couldn't something like ASDF or mudballs be used instead?. (Recently, I've been doing quite some Common Lisp, and *started* to enjoy system definition software). Though I don't know how easy it is to define without an object system behind…
Of course makefiles work, and there's no reason to change something that works. Yet, in our case, I think that it's still time not to do the mistake of choosing make from the beginning. A complete self-consistent system may be better.
P!
I attempted to install gambit and run this trivial script on a windows xp SP3 system.
@;gsi-script %~f0 %* (display "Hello world")
It failed. Blurted out a large quantity of of unintelligible characters to the command window.
When I inspected the directory C:\Program Files\Gambit-C\v4.4.4\bin I found the file gsi-script.bat to be 3.2 meg of illegible data. Since the size of several other .bat files were the same, I checked their md5sums, this is what I got... all the same value.
bb28d7131a5d49064c34ef045b9bc003 *gsi-script.bat bb28d7131a5d49064c34ef045b9bc003 *scheme-ieee-1178-1990.bat bb28d7131a5d49064c34ef045b9bc003 *scheme-r4rs.bat bb28d7131a5d49064c34ef045b9bc003 *scheme-r5rs.bat bb28d7131a5d49064c34ef045b9bc003 *scheme-srfi-0.bat bb28d7131a5d49064c34ef045b9bc003 *six-script.bat
I uninstalled, re-downloaded, re-installed. The problem persisted.
This is it the install package:
"gambc-v4_4_4-windows-mingw.exe"
My conclusion is that the setup program is somehow corrupt. Can someone corroborate or refute this for me please.
If it is corroborated, can someone please re-create a correct version of the setup program, so that I can install it properly.
TIA
BTW here is the md5sum output for the one I downloaded: 5e4ed22287220e7c43f2d445198c396c *gambc-v4_4_4-windows-mingw.exe
On 22-Jun-09, at 12:04 AM, Pierre Bernatchez wrote:
I attempted to install gambit and run this trivial script on a windows xp SP3 system.
@;gsi-script %~f0 %* (display "Hello world")
It failed. Blurted out a large quantity of of unintelligible characters to the command window.
Indeed these files seem to be corrupted. I guess I introduced a bug in the makefiles when I added logic to create files with the proper end-of-line encoding for Windows (CR-LF). For now, all the .bat files you mention can be recreated manually. They should contain the single line:
@gsi %*
except gsc-script.bat which should contain
@gsc %*
Marc