[m-users.] Memory allocation from C back into Mercury
Sean Charles (emacstheviking)
objitsu at gmail.com
Tue Aug 30 05:23:38 AEST 2022
OK, I have solved my issue. I found some old posts from 2019 that I made regarding SDL2 structures and the reply chain from there led me to use 'MR_GC_malloc' and it all looks to be just fine now.
Just in case anybody else finds it useful, here is the central piece of allocation code
size_t c_length = (sizeof(char) * chunk.size) + 1;
char* the_string = (char*)MR_GC_malloc(c_length);
if (the_string) {
memcpy(the_string, &chunk.memory[0], chunk.size);
Response = makeResponse(HttpStatus, the_string);
}
else {
Response = makeError(""Failed to allocate string"");
}
...and the modified function that returns my curl_response record:
:- func make_response(int::in, string::in)
= (io.res(curl_response)::out) is det.
make_response(HttpStatus, Content) = Out :-
trace[io(!Dbg), runtime(env("MCURL_DEBUG"))]
(
io.format("make_response:\n%s\n", [s(Content)], !Dbg)
),
Out = ok(curl_response(HttpStatus, Content, [])).
:- pragma foreign_export("C", make_response(in, in)
= (out), "makeResponse").
When I run this now I get the following output,
➜ mercury-libcurl ./mcurl https://google.com
GET https://google.com
* 220 bytes retrieved
* opened and cleaned up OK
HTTP: 301, length: 220
Content:
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://www.google.com/">here</A>.
</BODY></HTML>
Which is great news as far as I am concerned, I can now review and refactor what I have and move on to doing POST, PUT etc.
Thanks again,
Sean.
> On 29 Aug 2022, at 18:05, Sean Charles (emacstheviking) <objitsu at gmail.com> wrote:
>
> Hi,
>
> I now have a working binding for libcurl that can do a GET and I am stuck trying to find a good example of how to allocate a mercury string to hand back into Mercury land.
> I have the same code from here: https://curl.se/libcurl/c/getinmemory.html <https://curl.se/libcurl/c/getinmemory.html>
>
> After a call succeeds, here is how I am currently handling to curl response:
>
> if (CURLE_OK == res) {
> printf(""* %lu bytes retrieved\\n"", (unsigned long)chunk.size);
> long HttpStatus;
> curl_easy_getinfo(ch, CURLINFO_RESPONSE_CODE, &HttpStatus);
> Response = makeResponse((int)HttpStatus);
> }
> else {
> Response = makeError(1, curl_easy_strerror(res));
> }
>
> The line in bold, here is where I need to be able to create a string with the data from chunk.memory, for the number of bytes received, chunk.size, this is where I am unsure how to continue. The makeResponse() code is:
>
>
> :- func make_response(int::in)
> = (io.res(curl_response)::out) is det.
>
> make_response(HttpStatus)
> = ok(curl_response(HttpStatus, "Data!", [])).
>
> :- pragma foreign_export("C", make_response(in)
> = (out), "makeResponse").
>
> with:
>
> :- type curl_header ---> curl_header(string, string).
> :- type curl_response
> ---> curl_response(
> status :: int,
> content :: string,
> headers :: list(curl_header)
> ).
>
>
> I am also unsure of how to map a C "long"; the curl call `curl_easy_getinfo(ch, CURLINFO_RESPONSE_CODE, &longVal);` expects a pointer to a long, which I am currently then casting to an integer given the known range of HTTP status codes, but in general, if I wanted to pass that into a mercury function, what type do I use given I am on M1 arm64, the C specs only state 'minimum width' of 32, so int32 springs to mind but is this the correct assumption ?
>
> The final intention is to be able to have enough HTTP support available so that I can use the average API out there, GET/POST/PUT/FETCH/OPTIONS, with a view to implementing support layer for using my SOLID POD from a Mercury command line application.
>
> Thanks,
>
> Sean.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20220829/79880ebd/attachment.html>
More information about the users
mailing list