Hi,
I need help figuring out how to make a simple asynchronous module to fetch an url and call a "callback" function inside another thread when its done, anyone can help me ?
I want a LUA function like this:
[CODE]HTTPFetch(function()
print("Fetch done !")
end)[/CODE]
This is my test module:
[CODE]
#include "GarrysMod/Lua/Interface.h"
#include <curl\curl.h>
#include <thread>
using namespace GarrysMod::Lua;
int HTTPFetch(lua_State* state)
{
std::thread t([state](){
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://google.com");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
}
});
return 0;
}
GMOD_MODULE_OPEN()
{
LUA->PushSpecial(GarrysMod::Lua::SPECIAL_GLOB);
LUA->PushString("HTTPFetch");
LUA->PushCFunction(HTTPFetch);
LUA->SetTable(-3);
return 0;
}
GMOD_MODULE_CLOSE()
{
return 0;
}
[/CODE]
Have a look at [url]https://github.com/bkacjios/gm_tmysql4/blob/master/src/gm_tmysql.cpp#L318-L331[/url]
[QUOTE=rtm516;50370196]Have a look at [url]https://github.com/bkacjios/gm_tmysql4/blob/master/src/gm_tmysql.cpp#L318-L331[/url][/QUOTE]
Thanks, can you explain me how to do something like this ? (The code is not working its just an example to show what i want):
[CODE]
int MyExampleFunction(lua_State* state)
{
int callbackfunc = -1;
if (LUA->GetType(1) == Type::FUNCTION)
{
LUA->Push(1);
callbackfunc = LUA->ReferenceCreate();
}
std::thread t([callbackfunc, state](){
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://google.com");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
LUA->ReferencePush(callbackfunc);
LUA->Call(1, 0);
}
});
return 0;
}
[/CODE]
where can i get a version of the curl library for this? (so i can test my code)
[QUOTE=rtm516;50370543]where can i get a version of the curl library for this? (so i can test my code)[/QUOTE]
I built CURL using cmake (visual studio 2013) from [url]https://codeload.github.com/curl/curl/zip/curl-7_48_0[/url]
There is the prebuilt binaries: [URL="https://www.dropbox.com/s/prxoh0cnqwj2zxh/CURL.zip?dl=0"]https://www.dropbox.com/s/prxoh0cnqwj2zxh/CURL.zip?dl=0[/URL]
Thanks !
Cant get it to compile something to do with 'winstock2.h' not existing, here is what i have anyway, dunno wether it will work, not that good at c++ modules
[CODE]
int HTTPFetch(lua_State* state)
{
int callbackfunc = -1;
if (LUA->GetType(1) == GarrysMod::Lua::Type::FUNCTION)
{
LUA->Push(1);
callbackfunc = LUA->ReferenceCreate();
}
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://google.com");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
LUA->ReferencePush(callbackfunc);
LUA->Call(1, 0);
}
return 0;
}
[/CODE]
Are you on linux ? On windows 'winsock2.h' is the socket header, and its native.
In your linker settings you need: ws2_32.lib;libcurl.lib
PS: The function like you are showing is not threaded/async, maybe its normal, you are in testing stage
PPS: Edited main code example (more precise)
[QUOTE=rtm516;50370632]Cant get it to compile something to do with 'winstock2.h' not existing, here is what i have anyway, dunno wether it will work, not that good at c++ modules
[CODE]
int HTTPFetch(lua_State* state)
{
int callbackfunc = -1;
if (LUA->GetType(1) == GarrysMod::Lua::Type::FUNCTION)
{
LUA->Push(1);
callbackfunc = LUA->ReferenceCreate();
}
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://google.com");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
LUA->ReferencePush(callbackfunc);
LUA->Call(1, 0);
}
return 0;
}
[/CODE][/QUOTE]
[QUOTE=Fox-Warrior;50370816]Are you on linux ? On windows 'winsock2.h' is the socket header, and its native.
In your linker settings you need: ws2_32.lib;libcurl.lib
PS: The function like you are showing is not threaded/async, maybe its normal, you are in testing stage
PPS: Edited main code example (more precise)[/QUOTE]
What you need to do is exchange the data between the primary thread that called your lua function and the thread that fetches the data.
Once the data is fetched you can not call it from the same thread, you have to pass it over to the primary thread again, a common trick is to register a Think hook that calls your C function, in there you poll the queue and run the callbacks.
Theres some code from my rather old socket library that you could use for sample code:
Fetching Data:
[URL]https://github.com/glua/gm_glsock/blob/master/src/BindingGLSock.cpp#L372-L390[/URL]
[URL]https://github.com/glua/gm_glsock/blob/master/src/GLSockTCP.cpp#L256-L278[/URL]
Received Data:
[URL]https://github.com/glua/gm_glsock/blob/master/src/GLSockTCP.cpp#L111-L132[/URL]
Polling:
[URL]https://github.com/glua/gm_glsock/blob/master/src/BindingGLSock.cpp#L560-L569[/URL]
[url]https://github.com/glua/gm_glsock/blob/master/src/SockMgr.h#L54-L74[/url]
Hope it helps
Sorry, you need to Log In to post a reply to this thread.