Calling SWI-Prolog via C based on a DLL - c

again I need help. I try to call SWI-Prolog via C based on a dll on windows.
In my C progam I want to use the function "consult_cooco". The C code looks like
#include "consult_cooco.h"
#include <SWI-Prolog.h>
int consult_cooco( char** strInput )
{
char *program = "consult_cooco";
char *plav[2];
int rval;
char* xmlstring;
term_t av;
predicate_t p;
/* make the argument vector for Prolog */
plav[0] = program;
plav[1] = NULL;
putenv("SWI_HOME_DIR=C:\\Program Files (x86)\\swipl");
if ( !PL_initialise(1, plav ) )
PL_halt(1);
av = PL_new_term_refs(2);
p = PL_predicate("start_dialog", 2, "user");
printf("consult_cooco:: input >> %s\n",*strInput);
// Prolog call: start_dialog('ohne Zitrone, mit Joghurt, Butter',XML).
av = PL_new_term_refs(2);
PL_put_atom_chars(av, *strInput);
if ( PL_call_predicate(NULL, PL_Q_NORMAL, p, av) )
{
rval = PL_get_atom_chars(av+1, &xmlstring);
printf(" >> xmlstring of %s is \n\n%s (returned %i)\n",*strInput,xmlstring,rval);
}
else
{
printf(" >> no answer found\n");
}
PL_halt(1);
return 0;
}
I created the dll by
swipl-ld -shared -dll -o consult_cooco -goal true consult_cooco.c dialog.pl -DLIKES_EXPORTS -v
I linked C sources by
gcc CooCoServer.o -static-libgcc -lws2_32 -L. -lconsult_cooco -I. -o startcoocoserver
Begin of my Prolog file dialog.pl looks like
start_dialog( InputString, XMLResult ) :-
create_individual_filename('dialog_','.debug',Filename),
tell(Filename),
process_input( InputString, WordList ),
do(WordList, XMLResult ),
told.
Without
putenv("SWI_HOME_DIR=C:\\Program Files (x86)\\swipl");
I got the error
[FATAL ERROR: Could not find system resources]
as described in SWI Prolog manual.
But still Prolog predicates can not be found, the error description is
ERROR: '$c_call_prolog'/0: Undefined procedure: start_dialog/2
start_dialog is defined in dialog.pl, see above.
My assumption is that plav[0] = "consult_cooco"; is wrong and no link to the Prolog file is found.
When using an exe file starting from a C main file by changing
int consult_cooco( char** strInput )
{
char *program = "consult_cooco";
to
int main( int argc, char** argv )
{
char *program = argv[0];
it works. It works also with
int main( int argc, char** argv )
{
char *program = "call_cooco";
What do I wrong when using the dll? What must be put into char *program?
Would appreciate your help very much.

Sorry for that, the answer is already given here:
I have to set
plav[0] = (char*)"startcoocoserver.exe";
plav[1] = (char*)"-x";
plav[2] = (char*)"dialog.exe";
and to use then
if(!PL_initialise(3, plav))
An additional building step is necessary
swipl --goal=true --stand_alone=true -o dialog -c dialog.pl
before doing the other steps. Then it works :)
PS: I did not found how to delete a question - admin, please do...

Related

Execute hello.c file by using file handlers in C

I'm trying my luck with C lately and I came across to this question where I'm stuck.
I've a hello.c file
CODE 1
#include<stdio.h>
#include<stdlib.h>
int main(){
printf("Hello World");
return 0;
}
I open this file and display the content using the following C program (CODE 2)
CODE 2
#include<fcntl.h>
#include<stdio.h>
int main() {
FILE *fd;
char ch;
fd = fopen("/home/hello.c","r");
if( fd != NULL ) {
while((ch = getc( fd )) != EOF){
putchar(ch);
}
}
return 0;
}
However, I want the output of this code to be Hello World, i.e output of the hello.c file which is read.
How can that be done?
In order to run a c file, first you need to compile it into machine code then execute it.
To compile it: run gcc source-file -o executable-file
To run, execute: executable-file
In order to to the same things in C, use system() function from <stdlib.h>
const char* tempFile = "./tempfile";
const char* sourceFile = "hello.c";
const char compileCommand[255];
sprintf(compileCommand, "gcc %s -o %s", sourceFile, tempFile);
system(compileCommand);
system(tempFile);
This code hasn't been tested.
Currently, in the second program, you are reading hello.c file. So the output of CODE2 will be the contents of hello.c. i.e. #include<stdio.h>...
For what you need, in CODE1, you need to write the output of the program into a separate file (say a.txt) and then read a.txt in CODE2.
Hope this is a sufficient hint for you to solve further.
Your "CODE 2" would have to invoke a C-compiler to compile "CODE 1" and then run it using system() or a function provided by your operating system.
BTW: It is either int main(void) or int main(int argc, char** argv), NOT int main().
As general solution, you may try also to have a look to a C interpreter, like Cling, and try to include it in your project.

OCaml shared lib for another shared lib

I am exploring some adventurous ideas.
TL:DR; gnumake is able to use loadable modules, I am trying to use that C barrier to use OCaml but have trouble with the OCaml runtime initializing.
I have this OCaml code:
(* This is speak_ocaml.ml *)
let do_speak () =
print_endline "This called from OCaml!!";
flush stdout;
"Some return value from OCaml"
let () =
Callback.register "speak" do_speak
and I also have this C code: (Yes, needs to use extra CAML macros but not relevant here)
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <gnumake.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>
#include <caml/memory.h>
#include <caml/alloc.h>
int plugin_is_GPL_compatible;
char *ocaml_speaker(const char *func_name, int argc, char **argv)
{
char *answer =
String_val(caml_callback(*caml_named_value("speak"), Val_unit));
printf("Speaking and got: %s\n", answer);
char *buf = gmk_alloc(strlen(answer) + 1);
strcpy(buf, answer);
/* receive_arg */
return buf;
}
int do_speak_gmk_setup()
{
printf("Getting Called by Make\n");
// This is pretty critical, will explain below
char **argv = {"/home/Edgar/foo", NULL};
caml_startup(argv);
printf("Called caml_startup\n");
gmk_add_function("speak", ocaml_speaker, 1, (unsigned int)1, 1);
return 1;
}
and I'm compiling it with this Makefile
all:
ocamlopt -c speak_ocaml.ml
ocamlopt -output-obj -o caml_code.o speak_ocaml.cmx
clang -I`ocamlc -where` -c do_speak.c -o do_speak.o
clang -shared -undefined dynamic_lookup -fPIC -L`ocamlc -where` -ldl \
-lasmrun do_speak.o caml_code.o -o do_speak.so
show_off:
echo "Speaker?"
${speak 123}
clean:
#rm -rf *.{cmi,cmt,cmi,cmx,o,cmo,so}
And my problem is that only printf("Getting Called by Make\n"); is going off when I add the appropriate load do_speak.so in the Makefile, caml_startup is not going off correctly. Now I am calling caml_startup because if I don't then I get an error of
Makefile:9: dlopen(do_speak.so, 9): Symbol not found: _caml_atom_table
Referenced from: do_speak.so
Expected in: flat namespace
in do_speak.so
Makefile:9: *** do_speak.so: failed to load. Stop.
And this is because of the way that clang on OS X does linking, see here for more details: http://psellos.com/2014/10/2014.10.atom-table-undef.html
I am kind of out of ideas... I need to create a C shared library out of OCaml code which then needs to be part of another C shared library from which I obviously don't have the original argv pointers that caml_startup wants. As my code sample show, I've tried faking it out, and also used caml_startup(NULL) and char **argv = {NULL}; caml_startup(argv) with similar lack of success. I don't know how else to initialize the runtime correctly.
I actually can't tell very well what you're asking. However, here's a comment on this part of your question:
I've tried faking it out, and also used caml_startup(NULL) and char **argv = {NULL}; caml_startup(argv) with similar lack of success. I don't know how else to initialize the runtime correctly.
As far as I know, the only reason for the argv argument of caml_startup is to establish the command-line arguments (for Sys.argv). If you don't need command-line arguments it should be OK to call like this:
char *arg = NULL;
caml_startup(&arg);
Technically argv is supposed to contain at least one string (the name of the program). So maybe it would be better to call like this:
char *argv[] = { "program", NULL };
caml_startup(argv);

header files and multiple c programs

I am trying to use two .c files together. I am lost at how to do this, I have a simple setup for each file but I get a undefined reference to format_lines error when I try to compile. Any help would be muchly appreciated;
formatter.h
#ifndef _FORMATTER_H_
#define _FORMATTER_H_
#include <stdio.h>
char **format_file(FILE *);
char **format_lines(char **, int);
void test();
#endif
formatter.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "formatter.h"
char **format_file(FILE *infile) {
return NULL;
}
char **format_lines(char **lines, int num_lines) {
char **result = NULL;
#ifdef DEBUG
result = (char **)malloc(sizeof(char *) * 2);
if (result == NULL) {
return NULL;
}
result[0] = (char *)malloc(sizeof(char) * 80);
if (result[0] == NULL) {
return NULL;
}
strncpy(result[0], "(machine-like voice) EXTERMINATE THEM!", 79);
result[1] = (char *)malloc(sizeof(char) * 2);
if (result[1] == NULL) {
return NULL;
}
result[1][0] = '\0';
#endif
}
void test(){
print("here");
}
and sengfmt.c
#include <stdio.h>
#include <stdlib.h>
#include "formatter.h"
int main(int argc, char *argv[]) {
test();
#ifdef DEBUG
printf("%s does nothing right now.\n", argv[0]);
#endif
exit(0);
}
When I try to compile, I just type this.
$ gcc sengfmt3.c
/tmp/cc7Ttgne.o: In function `main':
sengfmt3.c:(.text+0x15): undefined reference to `test'
collect2: ld returned 1 exit status
I suspect that your main used to try to call format_lines
You need to do this
gcc formatter.c sendgfmt.c -o myprog
You must list all the c files that you want compiled together
If you have code in multiple source files, then you need to build with all the source files.
There are two ways of doing this:
Compile and link all source files using using one command:
$ gcc sengfmt3.c someOtherSourceFile.c someThirdSourceFile.c
First make object files of all source files, and then link the object files together. This is more work, but if you have a makefile or other build-system it will be better since only the modified source files will be recompiled, and might save you some build-time:
$ gcc -c sengfmt3.c
$ gcc -c someOtherSourceFile.c
$ gcc -c someThirdSourceFile.c
$ gcc sengfmt.o someOtherSourceFile.o someThirdSorceFile.o
Note the command-line option -c for the compilation, this tells GCC to generate object files. Also note that for the linking command (the last one) the file extensions have changed from .c to .o.
The command in point 1 does this internally, using temporary files which are removed when done.

int main(int argc, const char * argv[]) AND file input

I've never used,
int main(int argc, const char * argv[])
For most programs, I usually just compile in terminal (using mac) using two separate C files, example…
gcc functions.c main.c
But now I need to use int main(int argc, const char * argv[])… I just don't know if I'm using it correctly. Heres some code…
I compile in the command line doing…
gcc main.c input.txt
terminal tells me…
ld: file too small for architecture x86_64
collect2: ld returned 1 exit status
NOTE my functions work (i tested without using file input) and are in main.c also… i just didn't include them in this post. Also, node is just a basic node struct to a linked list.
int main(int argc, const char * argv[])
{
FILE *input;
input = fopen(argv[1], "r");
node *list = malloc(sizeof(node));
char *string = malloc(sizeof(char)*1023);
fscanf(input, "%s", string);
//convert a string to linked list
list= sTol(string);
//print the linked list
printList(list);
return 0;
} // end main()
Am i completely wrong? the input simply contains one line that says 'hello'. All I'm trying to do is read that into my program and print it just to verify I'm reading my input correctly.
This is not like a perl script or shell script, where you run
perl main.pl input.txt
With a compiled language like C, you first compile the program into an executable
gcc main.c -o myprogram
and then run the executable with the input file
./myprogram input.txt

When I include git2.h from libgit2, I can access data structures, but not functions

Here is some code from Ben Straub's (link blog) that I am basing this on:
static int do_clone(const char *url, const char *path)
{
git_repository *repo = NULL;
int ret = git_clone(&repo, url, path, NULL);
git_repository_free(repo);
return ret;
}
And here is my code:
#include <git2.h>
int main(void) {
git_repository *out = NULL;
git_clone(&out, "https://github.com/lehitoskin/racketball", "/home/maxwell", NULL);
return 0;
}
I am very inexperienced with C, so I apologize for having such elementary problems. Anyway, here is the error my compiler gives me:
maxwell#max-pc ~ $ gcc -I libgit2/include gitfun.c
/tmp/ccB64nPh.o: In function `main':
gitfun.c:(.text+0x31): undefined reference to `git_clone'
collect2: error: ld returned 1 exit status
Why can't I call git_clone this way?
It looks like you didn't link to the library. Add -lgit2 if libgit2 is the lib name.
gcc -I libgit2/include gitfun.c -L<path to lib> -l<libname minus the "lib" part>
IOW, you compile fine but when the linker goes looking for git_clone it can't find it because you haven't specified the library that it is in.

Resources