curl_easy_setopt fails on 64 bit CentOS 6

Linux specific forum
User avatar
mariosk8s
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Apr 06, 2011 11:37 am
Location: Hüfingen, Germany
Contact:

curl_easy_setopt fails on 64 bit CentOS 6

Post 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.
Fred
Administrator
Administrator
Posts: 18161
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post by Fred »

You can't call such variable argument functions in PB directly, you will need a wrapper.
User avatar
mariosk8s
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Apr 06, 2011 11:37 am
Location: Hüfingen, Germany
Contact:

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post by mariosk8s »

Then why is this working everywhere else? Luck?
Fred
Administrator
Administrator
Posts: 18161
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post 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.
User avatar
mariosk8s
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Apr 06, 2011 11:37 am
Location: Hüfingen, Germany
Contact:

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post 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
Last edited by mariosk8s on Mon Sep 16, 2013 2:13 pm, edited 1 time in total.
Fred
Administrator
Administrator
Posts: 18161
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post by Fred »

Just perfect.
User avatar
mariosk8s
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Apr 06, 2011 11:37 am
Location: Hüfingen, Germany
Contact:

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post by mariosk8s »

Now i only need the windows version of

Code: Select all

ImportC "-lcurl" : EndImport
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post 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)
Windows 11, Manjaro, Raspberry Pi OS
Image
Fred
Administrator
Administrator
Posts: 18161
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post by Fred »

The problem is it won't work for all scenarios:

for example printf in C:

Code: Select all

printf("%f", 10.0f)
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.
User avatar
mariosk8s
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Apr 06, 2011 11:37 am
Location: Hüfingen, Germany
Contact:

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post 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 :cry:
User avatar
mariosk8s
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Apr 06, 2011 11:37 am
Location: Hüfingen, Germany
Contact:

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post 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'.
sec
Enthusiast
Enthusiast
Posts: 792
Joined: Sat Aug 09, 2003 3:13 am
Location: 90-61-92 // EU or ASIA
Contact:

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post by sec »

.o is for object
.lib is for windows?
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post 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
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
mariosk8s
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Apr 06, 2011 11:37 am
Location: Hüfingen, Germany
Contact:

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post 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.
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: curl_easy_setopt fails on 64 bit CentOS 6

Post 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

Code: Select all

ImportC "-lcurl"
...
EndImport
http://www.purebasic.fr/english/viewtop ... 4&start=11
Post Reply