Page 1 of 2
curl_easy_setopt fails on 64 bit CentOS 6
Posted: Fri Sep 13, 2013 11:21 am
by mariosk8s
The following code segfaults on 64 bit CentOS 6 running libcurl-7.19
It runs fine on 64 bit Ubuntu 11.10 with libcurl-7.21 and 32 bit Linux Ubuntu or CentOS 6, Mac and Windows.
footest.pb
Code: Select all
#CURLOPT_URL = 10002
Global CURL_LIBRARYID = 0
PrototypeC curl_easy_init()
PrototypeC curl_easy_setopt(handle.i, curlOpt, *value)
PrototypeC curl_easy_perform(handle.i)
PrototypeC curl_easy_cleanup(handle.i)
Global curl_easy_init.curl_easy_init
Global curl_easy_setopt.curl_easy_setopt
Global curl_easy_perform.curl_easy_perform
Global curl_easy_cleanup.curl_easy_cleanup
Procedure loadCurl()
CURL_LIBRARYID = OpenLibrary(#PB_Any, "libcurl.so.4")
If CURL_LIBRARYID = 0
ProcedureReturn #False
EndIf
curl_easy_init = GetFunction(CURL_LIBRARYID, "curl_easy_init")
curl_easy_setopt = GetFunction(CURL_LIBRARYID, "curl_easy_setopt")
curl_easy_perform = GetFunction(CURL_LIBRARYID, "curl_easy_perform")
curl_easy_cleanup = GetFunction(CURL_LIBRARYID, "curl_easy_cleanup")
ProcedureReturn #True
EndProcedure
If loadCurl()
Define curl_Handle.i = curl_easy_init()
Define stringValue.s = "http://google.com"
curl_easy_setopt(curl_Handle.i, #CURLOPT_URL, @stringValue.s)
curl_easy_perform(curl_Handle)
curl_easy_cleanup(curl_Handle)
EndIf
It seems it's set setopt call that knocks the stack to smitherines. The interface for setopt is
Code: Select all
CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
It's not clear to me why this happens or how to work around this.
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Fri Sep 13, 2013 1:17 pm
by Fred
You can't call such variable argument functions in PB directly, you will need a wrapper.
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Fri Sep 13, 2013 1:33 pm
by mariosk8s
Then why is this working everywhere else? Luck?
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Fri Sep 13, 2013 1:41 pm
by Fred
Yes, just luck. PB doesn't support this notation, so args are arbitrary pushed on the stacks on x86 and using regs on x64, but the interpretation depends of the type. Better write a small wrapper in C to handle that.
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Fri Sep 13, 2013 2:02 pm
by mariosk8s
Thanks for the insight, Fred.
I already did.
Here's what i did for others, who fall into this trap, to read.
The c wrapper rfsetopt.c
Code: Select all
#include <curl/curl.h>
#if defined(WIN32) || defined(_WIN32)
# define API __declspec(dllexport)
#else
# define API
#endif
#ifdef __cplusplus
extern "C" {
#endif
API CURLcode
rf_curl_easy_setopt(CURL *curl, CURLoption tag, void* value) {
return curl_easy_setopt(curl, tag, value);
}
#ifdef __cplusplus
} /* extern "C" */
#endif
This puppy works.
Then i build it
Code: Select all
gcc -c rfsetopt.c -o rfsetopt.o -fPIC
Then here the updated footest.pb
Code: Select all
#CURLOPT_URL = 10002
Global CURL_LIBRARYID = 0
PrototypeC curl_easy_init()
PrototypeC curl_easy_perform(handle.i)
PrototypeC curl_easy_cleanup(handle.i)
Global curl_easy_init.curl_easy_init
Global curl_easy_perform.curl_easy_perform
Global curl_easy_cleanup.curl_easy_cleanup
ImportC "-lcurl" : EndImport
ImportC "rfsetopt.o"
curl_easy_setopt.i(handle.i, curlOpt, *value) As "rf_curl_easy_setopt"
EndImport
Procedure loadCurl()
CURL_LIBRARYID = OpenLibrary(#PB_Any, "libcurl.so.4")
If CURL_LIBRARYID = 0
ProcedureReturn #False
EndIf
curl_easy_init = GetFunction(CURL_LIBRARYID, "curl_easy_init")
curl_easy_perform = GetFunction(CURL_LIBRARYID, "curl_easy_perform")
curl_easy_cleanup = GetFunction(CURL_LIBRARYID, "curl_easy_cleanup")
ProcedureReturn #True
EndProcedure
If loadCurl()
Define curl_Handle.i = curl_easy_init()
Define stringValue.s = "http://google.com"
curl_easy_setopt(curl_Handle.i, #CURLOPT_URL, @stringValue.s)
curl_easy_perform(curl_Handle)
curl_easy_cleanup(curl_Handle)
EndIf
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Fri Sep 13, 2013 2:15 pm
by Fred
Just perfect.
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Fri Sep 13, 2013 3:58 pm
by mariosk8s
Now i only need the windows version of
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Fri Sep 13, 2013 11:25 pm
by idle
when you import varargs functions, can't you just add a null to the import ?
CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
PrototypeC curl_easy_setopt1(*curl,tag,void=0)
PrototypeC curl_easy_setopt2(*curl,tag,tag1,void=0)
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Sat Sep 14, 2013 9:17 am
by Fred
The problem is it won't work for all scenarios:
for example printf in C:
The first arg is a double, and then should be loaded in a double register in x64
now in PB:
Code: Select all
PrototypeC printf(format,arg,void=0)
printf("%f", 10.0)
Your arg will still be an integer and the call will fail. So you would need a prototype for any combinations of your format string to have this work. That said, it could work if you just need to pass integer var args.
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Mon Sep 16, 2013 7:37 am
by mariosk8s
Those are great tips. I'll use those on Windows for now as still don't know how to get linking to work.
Code: Select all
ImportC "/DEFAULTLIB:" + "c:/path/to/libcurl.dll" : EndImport
Fails

Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Mon Sep 16, 2013 7:43 am
by mariosk8s
Oh, yeah, let me define "Fails".
Code: Select all
Error: Linker
POLINK: warning: No subsystem specified; assuming CONSOLE.
POLINK: fatal error: Corrupt library: 'c:/path/to/libcurl.dll'.
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Mon Sep 16, 2013 7:49 am
by sec
.o is for object
.lib is for windows?
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Mon Sep 16, 2013 8:02 am
by idle
you can only use Import on a lib, if you don't have a lib for the dll you can make one with polib
from pellesC, can't remember the command for it, something like >Polib foo.dll /OUT:foo.lib
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Mon Sep 16, 2013 2:22 pm
by mariosk8s
@sec Yeah, just the object file worked for posix.
@idle thanks for that tip. So ran
Code: Select all
polib.exe libcurl.dll /OUT:libcurl.lib
Then i updated the c wrapper to include the cdecl stuff.
The trying to link gives me:
Code: Select all
polink.exe -DLL rfsetopt.o -OUT:rfsetopt.dll -DEFAULTLIB:/path/to/libcurl.lib
POLINK: error: Unresolved external symbol '_curl_easy_setopt'.
POLINK: error: Unresolved external symbol '___DllMainCRTStartup@12'.
POLINK: fatal error: 2 unresolved external(s).
I'm not sure about the polink call being correct as google is completely void of polink examples in this regard.
Re: curl_easy_setopt fails on 64 bit CentOS 6
Posted: Mon Sep 16, 2013 3:19 pm
by Shardik
You shouldn't need to generate a libcurl.lib for Linux. Just install the developer version of libcurl (tested on Kubuntu 12.04 LTS x86) and import libcurl with
http://www.purebasic.fr/english/viewtop ... 4&start=11