Dear Denys
could you please configure your mailer to insert a valid email address? thanks
Sorry about that, I hope it's OK now.
To clarify a couple of things:
you do know that downloading through HTTP and FTP is already supported
transparently, right?
Yes! But, AFAIK, I cannot POST to a URL (as if I was submitting a
form). That's why I thought I would try cURL. Is there something I've
missed? Is there an easy way to submit a "POST"??
please use ozmake instead. it is part of the distro. it won't solve your
problem, but it is the right tool these days for developing, contributing and
installing packages.
Urm, OK. I would do, once the thing got going, anyway...
There is no way we can help you without seeing the code.
I appreciate that. Just didn't want to upload anything if no-one was
interested. Code follows...
You have set yourself a very difficult task for your first foray into the world
of Mozart/Oz native functor design. IO is quite difficult to do right: you
[..etc]
I appreciate your offer, although I believe that the problem may be
something much simpler, mainly due to my own ignorance.
I don't see how I could have blocked the I/O, in any case, I imagine
that letting libcurl do the I/O will allow the web page to be passed
back as a simple value, the way PHP, Perl, Python, et al do it.
I can actually invoke the curl executable from Oz at the moment using
the shell/pipe method described in the Open Programming Tutorial, but I
thought it would be nice to have something more integrated.
I am following the "C interfacing" documentation pretty much to the letter.
Below is a skeletal view of the C stuff I used. I apologise, it's just
a very messy hack at the moment to see IF it will work. For instance,
the handle to libcurl is global, so that I don't have to pass it back
and forth to Mozart.
The funny thing is that if I compile it as an executable, with the main
routine below, it WORKS FINE!!!
When I try to use it from Oz (code below, after C), it ONLY finds and
fetches URLs on my local home network! All the others return a curl
code 7 (can't connect). At first I thought nothing worked, but then I
realised that it was OK with local net addresses. Too weird for me.
==================================================================================
#include "/usr/lib/mozart/include/mozart.h"
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <dlfcn.h>
// for now a unique global, but will need to be local
CURL *curl_handle = 0;
// The file handles for the transfered data and errors
FILE * datafile = stdout;
FILE * errfile = stderr;
#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 *);
#else
// the pointers just point to the static functions
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;
// if we are linking statically, just use the defined functons
#endif // _USING_LINUX_DLL
// =================== dummy test stuff
char oz_module_name[] = "Mozart-libcurl";
#ifdef _USING_LINUX_DLL
// 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 0;
// get the functions we'll be using (as global pointers)
// we may add failure chacks here later, but for now
// I think it's safe to assume that if the dl opened, the fns 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);
}
#endif // _USING_LINUX_DLL
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){
// if transfer files are open, close them
if (datafile!=stdout) fclose(datafile);
if (errfile!=stderr) fclose(errfile);
//
p_curl_easy_cleanup(curl_handle);
dlclose(dll_handle);
// return any error codes, for now
OZ_RETURN_INT(1);
}
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},
{0,0,0,0}
} ; // ***ag***
OZ_C_proc_interface * oz_init_module(void){
return table;
}
=========================================
This is the Oz code I use to check the returns
it all seems fine... except I can only access local URLs!!
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}
{Browse H}
{Browse R1}
{Browse R2}
{Browse R3}
{Browse RC} %% for some reason this returns 7 (no connection) for URLs
not on local network, instead of 0 (all OK, transfer done)
RX = {Curl.close 123}
%% 123 is a dummy value, placeholder for the handle, which is global at
the moment, while testing.
=============================
FWIW this is the main routine I used, and which worked fine for all URLs
(sheesh)
int main(int argc, char *argv[]) {
int rc;
if(!setup_dll()) return 10;;
curl_handle = p_curl_easy_init();
//
if (!curl_handle) printf("whoops\n");
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;
}
_________________________________________________________________________________
mozart-users mailing list
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users