ΟΚ, here's the code, nothing special


#include <stdio.h>
#include <string.h>
//#include <string>
#include <curl/curl.h>
#include <dlfcn.h>
#include "/usr/lib/mozart/include/mozart.h"
// using namespace std;

// for now a unique global, but will need to be local
CURL *curl_handle = 0;

cURL lets us write the URL data either directly to stdout, or to some file,
or to a callback function. For now, use a file.
// The file handles for the transfered data and errors
FILE * datafile;
FILE * errfile;

Once it's working in C, will use C++ for the string class etc.
//global C++ strings, for storing params as required by cURL
//string urlstr, agentstr;

char oz_module_name[] = "Mozart-libcurl";

#define _USING_LINUX_DLL // if we are doing a dynamic rather than a static link

#ifdef _USING_LINUX_DLL
// global dll handle
void *dll_handle = 0;
// define the pointers to the corresponding functions
// that will be got from the dll
CURL * (*p_curl_easy_init)();
CURLcode (*p_curl_easy_setopt)(CURL*, CURLoption,...);
CURLcode (*p_curl_easy_perform)(CURL*);
void (*p_curl_easy_cleanup)(CURL *);

// get the function pointers from the dll
int setup_dll() {
// open the dll
dll_handle = dlopen("/usr/lib/libcurl.so", RTLD_LAZY);
if (!dll_handle) return FALSE;

// get the functions we'll be using (as global pointers)
// we may add failure checks here later, but for now
// I think it's safe to assume that if the dl opened, the funcs are there...
p_curl_easy_init = (CURL* (*)())dlsym(dll_handle,"curl_easy_init");
p_curl_easy_cleanup = (void (*)(CURL*))dlsym(dll_handle,"curl_easy_cleanup");
p_curl_easy_setopt = (CURLcode(*)(CURL*,CURLoption,...))dlsym(dll_handle,"curl_easy_setopt");
p_curl_easy_perform = (CURLcode(*)(CURL*))dlsym(dll_handle,"curl_easy_perform");

return TRUE;
}

void cleanup_dll() {
dlclose(dll_handle);
}

#else

// if we are linking statically, just use the defined functons
CURL * (*p_curl_easy_init)() = curl_easy_init;
CURLcode (*p_curl_easy_setopt)(CURL*, CURLoption,...) = curl_easy_setopt;
CURLcode (*p_curl_easy_perform)(CURL*) = curl_easy_perform;
void (*p_curl_easy_cleanup)(CURL*) = curl_easy_cleanup;

#endif // _USING_LINUX_DLL

This is how the macros for the C interface are spec'd

// =================== dummy test stuff

static long n;

OZ_BI_define(counter_next,0,1){
OZ_RETURN_INT(n++);
}
OZ_BI_end


// ===================

OZ_BI_define(easy_entry_init,0,1) {

#ifdef _USING_LINUX_DLL
// get the function pointers from the dll
if (!setup_dll()) return OZ_FAILED;
#endif // _USING_LINUX_DLL

// **********************************************
// initialise curl hadle here (currently global)
// will change this - after testing
// **********************************************
curl_handle = p_curl_easy_init();
if (!curl_handle) return OZ_FAILED;

// return handle
OZ_RETURN_INT((int)curl_handle);
}
OZ_BI_end

OZ_BI_define(easy_setopt,3,1){
CURLcode rc;

OZ_declareAtom(1,curlOptionStr);

CURLoption curlOpt =
(!strcmp(curlOptionStr,"CURLOPT_URL")) ? CURLOPT_URL :
(!strcmp(curlOptionStr,"CURLOPT_WRITEDATA")) ? CURLOPT_WRITEDATA :
(!strcmp(curlOptionStr,"CURLOPT_POSTFIELDS")) ? CURLOPT_POSTFIELDS :
(!strcmp(curlOptionStr,"CURLOPT_POST")) ? CURLOPT_POST :
(!strcmp(curlOptionStr,"CURLOPT_STDERR")) ? CURLOPT_STDERR :
(!strcmp(curlOptionStr,"CURLOPT_USERAGENT")) ? CURLOPT_USERAGENT :
(CURLoption)0 ;

if(curlOpt==0) // unrecognised otion, return
OZ_RETURN_INT(1); // (1 = unsupp. protocol... that'll do)


// Assume only one parameter for now but some options have multiple params
// third setopt param. declared as ellipsis - may pass as list in future...??
OZ_declareAtom(2,curlParameter);

// OK, process the option
switch(curlOpt) {
case CURLOPT_WRITEDATA :
// pass file handle - remember to close
if(!(datafile=fopen(curlParameter,"w"))) OZ_RETURN_INT(100);
rc = p_curl_easy_setopt(curl_handle, curlOpt, datafile);
break;
case CURLOPT_STDERR :
// pass file handle - remember to close
if(!(errfile=fopen(curlParameter,"w"))) OZ_RETURN_INT(100);
rc = p_curl_easy_setopt(curl_handle, curlOpt, errfile);
break;
default:
rc = p_curl_easy_setopt(curl_handle, curlOpt, curlParameter);
}

OZ_RETURN_INT(rc);
}
OZ_BI_end

OZ_BI_define(easy_perform_exec,1,1){
CURLcode rc = p_curl_easy_perform(curl_handle);
OZ_RETURN_INT(rc);
}
OZ_BI_end

OZ_BI_define(easy_cleanup_exit,1,1){
CURLcode rc=(CURLcode)0;

// if transfer files are open, close them
if (datafile!=stdout) fclose(datafile);
if (errfile!=stderr) fclose(errfile);

// tidy up curl stuff
p_curl_easy_cleanup(curl_handle);

#ifdef _USING_LINUX_DLL
if(dlclose(dll_handle)) // non-zero return implies error
rc=(CURLcode)20;
#endif // _USING_LINUX_DLL

OZ_RETURN_INT(rc);
}
OZ_BI_end


OZ_C_proc_interface table[] = {
{"init",0,1,easy_entry_init},
{"setopt",3,1,easy_setopt},
{"exec",1,1,easy_perform_exec},
{"close",1,1,easy_cleanup_exit},
{"next",0,1,counter_next},
{0,0,0,0}
} ;

OZ_C_proc_interface * oz_init_module(void){
n=1;
return table;
}


  
This is the main routine, which is working fine, with no problems.

int main(int argc, char *argv[]) {
int rc;
n=0;
datafile = stdout;
errfile = stderr;

if(!setup_dll()) return 10;;

curl_handle = p_curl_easy_init();

// check curl handle
if (!curl_handle) {
printf("whoops!\n");
}
else {
char url[] = "http://www.mozart-oz.org";

rc = p_curl_easy_setopt(curl_handle, CURLOPT_URL, url);
printf("setopt-url = %d\n",rc);

rc = p_curl_easy_perform(curl_handle);
printf("\nperform = %d\n", rc);

p_curl_easy_cleanup(curl_handle);
}

cleanup_dll();

return 0;
}


This is the Oz program that uses the module.
It ONLY finds the URL if it's in the local network...
"123" is a temp dummy for the curl-handle, which is used as a global for now,
just to keep things as simple as possible...

declare [Curl] = {Module.link ['/home/alex/Code/c/ozlibcurl.so{native}']}

H = {Curl.init}
R1 = {Curl.setopt 123 'CURLOPT_URL' 'http://www.mozart-oz.org'}
R2 = {Curl.setopt 123 'CURLOPT_WRITEDATA' './somedata.txt'}
R3 = {Curl.setopt 123 'CURLOPT_STDERR' './some-err.txt'}
RC = {Curl.exec 123}
J = {Curl.close 123}

{Browse {Curl.next }}
{Browse H}
{Browse R1}
{Browse R2}
{Browse R3}
{Browse RC}
{Browse J}