Extern of varargs?

BlitzMax Forums/BlitzMax Programming/Extern of varargs?

So I am trying to wrap just the "easy" part of libcurl. I have to come up with a way to Extern this function:

CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);


In C, this function takes an option, then an arbitrary data type:

curl_easy_setopt(curl, CURLOPT_POST, 0); 
curl_easy_setopt(curl, CURLOPT_URL, "urlStr"); 
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlData); 


How do you Extern varargs?

Well, I can't find any information on reading how variadic arguments are handled without stdarg.h (probably something out there, but it's harder to find than what I'll do), so I'll take a look at the curl_easy_setopt source and see what options there are for this.

I would imagine that, since BMax doesn't (yet, hopefully one day) support function overloading, you would need to declare four functions, one for each datatype.

i.e.
curl_easy_setopt_long
curl_easy_setopt fp
curl_easy_setopt_obj
curl_easy_setopt_cot

Best I can think of is doing something like this:
Extern "C"
    Function curl_easy_setopt@ Ptr( curl@ Ptr, opt%, data@ Ptr )
EndExtern

' ex. 1
curl_easy_setopt( curl, CURLOPT_POST, Byte Ptr(0) )

' ex. 2
Local s@ Ptr = "Pie".ToCString( )
curl_easy_setopt( curl, CURLOPT_URL, s )
MemFree( s )

curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, curlData )


Looking at the curl source it never uses more than one argument in the va_list (seems they're just using it as a sort of storage container for whatever data type they like). As such, may as well just do this.

It's not pretty, and you might want to consider something like this:
Extern "C"
    Function curl_easy_setopt_ptr@ Ptr( curl@ Ptr, opt%, data@ Ptr )="curl_easy_setopt"
    Function curl_easy_setopt_str@ Ptr( curl@ Ptr, opt%, data$z )="curl_easy_setopt"
EndExtern

Don't know if that works, though. You'll have to try yourself, frankly, as I can't get into building this stuff myself.

Thanks, guys. I will try this out tomorrow and post back with results!

So, to keep everyone informed, here's an update:

Strict

Const CURLOPT_VERBOSE = 41
Const CURLOPT_POST = 47
Const CURLOPT_URL = 10002
Const CURLOPT_WRITEFUNCTION = 20011
Const CURLOPT_CAINFO = 10065

Global libcurl=LoadLibraryA("libcurl-4.dll")

'CURL_EXTERN CURL *curl_easy_init(void);
Global curl_easy_init:Byte Ptr()"win32" = getProcAddress(libcurl, "curl_easy_init")

'CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
Global curl_easy_setopt_int:Int(curl:Byte Ptr, curlOption:Int, val:Int)"win32" = getProcAddress(libcurl, "curl_easy_setopt")
Global curl_easy_setopt_str:Int(curl:Byte Ptr, curlOption:Int, val:String)"win32" = getProcAddress(libcurl, "curl_easy_setopt")
Global curl_easy_setopt_ptr:Int(curl:Byte Ptr, curlOption:Int, val:Byte Ptr)"win32" = getProcAddress(libcurl, "curl_easy_setopt")

'CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
Global curl_easy_perform:Int(curl:Byte Ptr)"win32" = getProcAddress(libcurl, "curl_easy_perform")

'CURL_EXTERN void curl_easy_cleanup(CURL *curl);
Global curl_easy_cleanup(curl:Byte Ptr)"win32" = getProcAddress(libcurl, "curl_easy_cleanup")

Local easyhandle:Byte Ptr = curl_easy_init()

curl_easy_setopt_int(easyhandle, CURLOPT_VERBOSE, 1)

' put the .crt file in your runtime dir
curl_easy_setopt_ptr(easyhandle, CURLOPT_CAINFO, "curl-ca-bundle.crt".toCString()) 
curl_easy_setopt_int(easyhandle, CURLOPT_POST, 0)
curl_easy_setopt_ptr(easyhandle, CURLOPT_URL, "url")

Local success:Int = curl_easy_perform(easyhandle)


Using this to connect to an ordinary http:// address seems to work, and the return stuff is put in the console. It is getting sent to stdout or stderr, I guess. I don't know how to capture that back into BMax, but I presume there is a way.

Using this to connect to https:// gives an unhandled memory exception error on curl_easy_perform, and I don't know why.