Topics

C reference mutation

 

I'm working on a curl wrapper and running into some difficulties trying to get Stanza to play along with the C pass-by-reference return argument pattern. I'm not sure if it's a limitation of my C skills or an actual limitation of Stanza's C interface.

My current attempt involves passing a variable via an intermediary C function and then using a simple get function to get at the contents but I'm not having any luck getting it to work.

Any help or advice on getting this package up to snuff would be greatly appreciated!

Thanks!

 

Typically when using libcurl you would create a function by setting CURLOPT_WRITEFUNCTION and then here is the signature expected:

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);

The userdata argument is actually set via CURLOPT_WRITEDATA and you can avoid creating your own function and just utilize the internal one, but you are then required to assign a pointer to CURLOPT_WRITEDATA otherwise libcurl will print to STDOUT.

I'd be interested in getting both patterns usable in Stanza but when I pass a pointer to CURLOPT_WRITEDATA it doesn't seem to get changed.

 

Hi Jake.

Apologies for the late reply. (It's tax season.) LoStanza is supposed to be capable of expressing that callback pattern. Can you give me some more information on how you're going about it, so I can help you debug? The link you posted results in a 404 error.

  -Patrick

 

Hey!

No problem on the reply, I only have a couple hours a day to even do any programming so I completely understand getting wrapped up in other things. With that said, I am about to head to work but I wanted to try and at least give you a clean link to use: https://gitlab.com/stanza-tools/curl/

I think I had my settings a little off in Gitlab for viewing repositories. The previous links should work correctly for you now as well.

I'll try to give you more detail this afternoon.

Thanks for the help!

~ Jake

 

Hi Jake.

I looked through your implementation and the only line that looks suspect is this one:

val c:int = call-c curl_easy_setopt(h.value, o.value, addr!(p.chars))

You are passing an unstable pointer to C. This is okay if you know, for sure, that no Stanza code will run while the C system hangs onto the pointer. This is because if the garbage collector happens to run, then the pointer will end up pointing to some random location in memory. So if C is going to hang on to the pointer, you should malloc a stable piece of memory and pass that instead.

Do you think that could be it?

  -Patrick


 

Patrick,

So I took your advice and applied it to the callback. I feel like I am close with these 2 commits I did tonight.

The first one prints some info and then overwrites the buffer. I was not getting an accumulated result but it was working.

The second commit tries (again my C skills means I'm mostly following how the CURL example shows it) to dynamically allocate a memory buffer instead of overwriting but I am getting a segmentation fault now.

Regarding the line you mention, I think that it is safe because if I don't try to save this data somewhere or with some callback, it prints the example.com html to STDOUT which means that the curl_easy_setopt call is working there.

Thanks again for taking a look!

~ Jake

 

Okay. I read through the curl_easy_setopt documentation, and it promises not to hang on to the char* pointer, so that part is indeed fine.

I may be overlooking something here, but you declare the following:

struct MemoryStruct *mem;

but I can't find the line that actually initializes that pointer. 

  -Patrick

 

Yeah this shows my lack of C skill right there :P

So I am now initializing the memory inside stz_curl_write_mem_cb_set and then passing it to the WRITEDATA option and I didn't have to modify the callback at all.

However, I am still getting a seg fault. Tonight I will try and see if there is a CURLCode being thrown somewhere that can help me decipher what's going on. If I run this through gdb, will it give me a useful backtrace?

You can check out the latest here.

 

As far as I can tell, the LoStanza half of your code is all fine. So the bug is probably from not using or initializing the curl library properly. If that's the case, then a gdb backtrace should be useful. It will tell you exactly which call to the curl library is failing.

  -Patrick