Have you defined the "native PrintFunc();" in your include or pwn file?
|
@Konstantinos
Did you register the natives in AmxLoad? The script will be aware of the natives only when you register them. The register process basically fills the native functions table (the PAWN compiler leaves the address field as 0) with the correct addresses. If there is one or more function whose address isn't set, you'll get that error. |
Does anyone manage to fix HTTP crash or find a way to use it ? I'm experiencing crashes or not calling at all. More you can find here https://github.com/Zeex/sampgdk/issues/164
|
segmentation fault (core dumped)
[debug] Server crashed due to an unknown error [debug] Native backtrace: [debug] #0 f7390ca0 in _Z13GetStackTraceRSt6vectorI10StackFrameSaIS0_EEPv () from plugins/crashdetect.so [debug] #1 f7389d22 in _ZN11CrashDetect20PrintNativeBacktraceERSoPv () from plugins/crashdetect.so [debug] #2 f738a314 in _ZN11CrashDetect20PrintNativeBacktraceEPv () from plugins/crashdetect.so [debug] #3 f738c964 in _ZN11CrashDetect11OnExceptionEPv () from plugins/crashdetect.so [debug] #4 f73905cd in ?? () from plugins/crashdetect.so [debug] #5 f7783bd0 in ?? () [debug] #6 f74f152f in ?? () from /lib32/libc.so.6 [debug] #7 f734b3b6 in ?? () from plugins/helloworld.so [debug] #8 f73e5345 in bsearch () from /lib32/libc.so.6 [debug] #9 f734b42e in ?? () from plugins/helloworld.so [debug] #10 f734b48b in ?? () from plugins/helloworld.so [debug] #11 f734b5ae in sampgdk_callback_init () from plugins/helloworld.so [debug] #12 f7347fde in sampgdk_module_init () from plugins/helloworld.so [debug] #13 f734cac2 in ?? () from plugins/helloworld.so [debug] #14 f734cb76 in ?? () from plugins/helloworld.so [debug] #15 f734cce6 in sampgdk_Load () from plugins/helloworld.so [debug] #16 f7347f5d in _ZN7sampgdk4LoadEPPv () from plugins/helloworld.so [debug] #17 f7347ed9 in Load () from plugins/helloworld.so [debug] #18 080d2742 in ?? () from ./samp03svr [debug] #19 080d2afa in ?? () from ./samp03svr [debug] #20 080aa0d0 in ?? () from ./samp03svr [debug] #21 f73d0637 in __libc_start_main () from /lib32/libc.so.6 [debug] #22 0804b4e1 in ?? () from ./samp03svr
After following the instructions on the wiki for setting up a CMake project, every time I try to run the plugin, I get a
Код:
segmentation fault (core dumped) Код:
[debug] Server crashed due to an unknown error [debug] Native backtrace: [debug] #0 f7390ca0 in _Z13GetStackTraceRSt6vectorI10StackFrameSaIS0_EEPv () from plugins/crashdetect.so [debug] #1 f7389d22 in _ZN11CrashDetect20PrintNativeBacktraceERSoPv () from plugins/crashdetect.so [debug] #2 f738a314 in _ZN11CrashDetect20PrintNativeBacktraceEPv () from plugins/crashdetect.so [debug] #3 f738c964 in _ZN11CrashDetect11OnExceptionEPv () from plugins/crashdetect.so [debug] #4 f73905cd in ?? () from plugins/crashdetect.so [debug] #5 f7783bd0 in ?? () [debug] #6 f74f152f in ?? () from /lib32/libc.so.6 [debug] #7 f734b3b6 in ?? () from plugins/helloworld.so [debug] #8 f73e5345 in bsearch () from /lib32/libc.so.6 [debug] #9 f734b42e in ?? () from plugins/helloworld.so [debug] #10 f734b48b in ?? () from plugins/helloworld.so [debug] #11 f734b5ae in sampgdk_callback_init () from plugins/helloworld.so [debug] #12 f7347fde in sampgdk_module_init () from plugins/helloworld.so [debug] #13 f734cac2 in ?? () from plugins/helloworld.so [debug] #14 f734cb76 in ?? () from plugins/helloworld.so [debug] #15 f734cce6 in sampgdk_Load () from plugins/helloworld.so [debug] #16 f7347f5d in _ZN7sampgdk4LoadEPPv () from plugins/helloworld.so [debug] #17 f7347ed9 in Load () from plugins/helloworld.so [debug] #18 080d2742 in ?? () from ./samp03svr [debug] #19 080d2afa in ?? () from ./samp03svr [debug] #20 080aa0d0 in ?? () from ./samp03svr [debug] #21 f73d0637 in __libc_start_main () from /lib32/libc.so.6 [debug] #22 0804b4e1 in ?? () from ./samp03svr |
typedef bool (SAMPGDK_CALLBACK_CALL *OnPlayerEditObject_callback)(int playerid, bool playerobject, int objectid, int response, float fX, float fY, float fZ, float fRotX, float fRotY, float fRotZ);
static bool _OnPlayerEditObject(AMX *amx, void *callback, cell *retval) {
bool retval_;
int playerid;
bool playerobject;
int objectid;
int response;
float fX;
float fY;
float fZ;
float fRotX;
float fRotY;
float fRotZ;
sampgdk_param_get_cell(amx, 0, (cell *)&playerid);
sampgdk_param_get_bool(amx, 1, (bool *)&playerobject);
sampgdk_param_get_cell(amx, 2, (cell *)&objectid);
sampgdk_param_get_cell(amx, 3, (cell *)&response);
sampgdk_param_get_float(amx, 4, (float *)&fX);
sampgdk_param_get_float(amx, 5, (float *)&fY);
sampgdk_param_get_float(amx, 6, (float *)&fZ);
sampgdk_param_get_float(amx, 7, (float *)&fRotX);
sampgdk_param_get_float(amx, 8, (float *)&fRotY);
sampgdk_param_get_float(amx, 9, (float *)&fRotZ);
sampgdk_log_debug("OnPlayerEditObject(%d, %d, %d, %d, %f, %f, %f, %f, %f, %f)", playerid, playerobject, objectid, response, fX, fY, fZ, fRotX, fRotY, fRotZ);
retval_ = ((OnPlayerEditObject_callback)callback)(playerid, playerobject, objectid, response, fX, fY, fZ, fRotX, fRotY, fRotZ);
if (retval != NULL) {
*retval = (cell)retval_;
}
return !!retval_ != true;
}
<and some more lines in other parts>
const bool Object::AttachToObject(int32_t ID, int32_t AttachToID, float X, float Y, float Z, float RotationX, float RotationY, float RotationZ, bool SyncRotation) { static AMX_NATIVE Native = sampgdk::FindNative("AttachDynamicObjectToObject"); return !!sampgdk::InvokeNative(Native, "iiffffffb", ID, AttachToID, X, Y, Z, RotationX, RotationY, RotationZ, SyncRotation); }
const Point3D<float> Object::GetPosition(int32_t ID) { Point3D<float> Restult; static AMX_NATIVE Native = sampgdk::FindNative("GetDynamicObjectPos"); sampgdk::InvokeNative(Native, "iRRR", ID, &Restult.X, &Restult.Y, &Restult.Z); return Restult; }
* \note In Pawn, variadic functions always take their variable arguments * (those represented by "...") by reference. This means that for such * functions you have to use the 'r' specifier where you would normally * use 'b', 'i' 'd' or 'f'.
const int SetTimerEx(const char * funcname, int interval, bool repeating, const char * format, ...) { static AMX_NATIVE Native = sampgdk::FindNative("SetTimerEx"); return sampgdk::InvokeNative(Native, "sibsr", funcname, interval, repeating, format, ???); }
template<typename... Args> const int SetTimerEx(const std::string& func_name, const int interval, const bool repeating, const size_t total_arguments, const std::string& format, Args&& ...args) { static AMX_NATIVE native = sampgdk::FindNative("SetTimerEx"); return sampgdk::InvokeNative(native, (std::string("sibs") + std::string(total_arguments, 'r')).c_str(), func_name.c_str(), interval, repeating, format.c_str(), std::forward<Args>(args)...); }
template<typename... Args> const int SetTimerEx(const std::string& func_name, const int interval, const bool repeating, const std::string& format, Args&& ...args) { static AMX_NATIVE native = sampgdk::FindNative("SetTimerEx"); return sampgdk::InvokeNative(native, (std::string("sibs") + std::string(format.length(), 'r')).c_str(), func_name.c_str(), interval, repeating, format.c_str(), std::forward<Args>(args)...); }
int test = 10; int test2 = 20; int test3 = 30; SetTimerEx("TestTimer", 1000, true, 3, "iii", &test, &test2, &test3);
PLUGIN_EXPORT bool PLUGIN_CALL OnPublicCall(AMX *amx, const char *name, cell *params, cell *retval) { auto Name = std::string(name); if (Name == "TestTimer") { std::cout << "TestTimer(" << params[1] << ", " << params[2] << ", " << params[3] << ")" << std::endl; } return true; }
template<typename... Args> const int SetTimerEx(const std::string& func_name, const int interval, const bool repeating, const std::string& format, Args&& ...args) { static AMX_NATIVE native = sampgdk::FindNative("SetTimerEx"); std::string function_format = "sibs"; for (size_t i = 0; i < format.length(); i++) { function_format += format[i] == 's' ? "s" : "r"; } return sampgdk::InvokeNative(native, function_format.c_str(), func_name.c_str(), interval, repeating, format.c_str(), std::forward<Args>(args)...); }
PLUGIN_EXPORT bool PLUGIN_CALL OnPublicCall(AMX *amx, const char *name, cell *params, cell *retval) { auto Name = std::string(name); if (Name == "TestTimer") { char string[7]; sampgdk_fakeamx_get_string(params[5], string, params[4] + 1); std::cout << "TestTimer(" << params[1] << ", " << params[2] << ", " << amx_ctof(params[3]) << ", \"" << string << "\")" << std::endl; } return true; }
extern void sampgdk_fakeamx_get_string(cell address, char *dest, int size);
int test = 10; int test2 = 20; float test3 = 30.456f; std::string test4 = "Hello!"; size_t test4_length = test4.length(); SetTimerEx("TestTimer", 1000, true, "iifis", &test, &test2, &test3, &test4_length, test4.c_str());
...
This is for AttachDynamicObjectToObject Код:
const bool Object::AttachToObject(int32_t ID, int32_t AttachToID, float X, float Y, float Z, float RotationX, float RotationY, float RotationZ, bool SyncRotation) { static AMX_NATIVE Native = sampgdk::FindNative("AttachDynamicObjectToObject"); return !!sampgdk::InvokeNative(Native, "iiffffffb", ID, AttachToID, X, Y, Z, RotationX, RotationY, RotationZ, SyncRotation); } |
namespace Plugins { namespace Streamer { namespace Object { int Create( int modelid, float x, float y, float z, float rx, float ry, float rz, int worldid = -1, int interiorid = -1, int playerid = -1, float streamdistance = STREAMER_OBJECT_SD, float drawdistance = STREAMER_OBJECT_DD, int areaid = -1, int priority = 0 ) { static AMX_NATIVE Native = sampgdk::FindNative( "CreateDynamicObject" ); return sampgdk::InvokeNative( Native, "iffffffiiiffii", modelid, x, y, z, rx, ry, rz, worldid, interiorid, playerid, streamdistance, drawdistance, areaid, priority ); } }; }; };
I don't have anything in mind for mysql_pquery, but you can try to use a single parameter as a class or a struct.
|
template< typename... Args > const bool pquery( int connectionHandle, const char query[ ], const char callback[ ] = "", const char format[ ] = "", Args && ... args ) { static AMX_NATIVE Native = sampgdk::FindNative( "mysql_pquery" ); std::string function_format = "isss"; for( int i = 0, s = std::strlen( format ); i < s; i ++ ) { function_format += ( format[ i ] == 's' ? "s" : "r" ); } return !!sampgdk::InvokeNative( Native, function_format.c_str( ), connectionHandle, query, callback, format, std::forward< Args >( args ) ... ); }
Plugins::MySQL::pquery( 1, "<query>", "Callback", "iii", &varint1, &varint2, &varint3 );
Originally Posted by mysql_log.html
Log("00:19:31","mysql_pquery",4,"connection: 1, query: \"<query>\", callback: \"Callback\", format: \"iii\"",0);
Log("00:19:31","CMySQLQuery::Execute[OnQueryFinish]",4,"starting query execution",1); Log("00:19:31","CMySQLQuery::Execute[Callback]",4,"starting query execution",1); Log("00:19:31","CMySQLQuery::Execute[Callback]",4,"query was successfully executed within x.xxx milliseconds",1); Log("00:19:31","CMySQLResult::CMySQLResult()",4,"c onstructor called",1); |
When you call SetTimer you will pass a void* for parameters, in your function you need to know how to use that void*, that's why he is using a struct for that (you can use a class). This is the easy way. But if you want to use std::tuple go ahead, take a look here to see how you can achieve that.
|
Timers::SetTimerEx( TimerFunction, 1000, 0, std::make_tuple( playerid, 10.0, "hello" ) ); void TimerFunction( int timerid, std::tuple< int, float, char * > params ) { int playerid = std::get< 0 >( params ); float posX = std::get< 1 >( params ); char * message = std::get< 2 >( params ); }
namespace Plugins { namespace SSCANF { template< typename... Args > const int unformat( const char data[ ], const char format[ ], Args * ... args ) { static AMX_NATIVE Native = sampgdk::FindNative( "sscanf" ); std::string function_format = "ss"; for( int i = 0, s = std::strlen( format ); i < s; i ++ ) { switch( format[ i ] ) { case 's': function_format += "S[128]"; break; case 'i': case 'd': case 'c': case 'l': case 'b': case 'h': case 'x': case 'o': case 'n': case 'f': case 'g': case 'u': case 'q': case 'r': function_format += "R"; break; default: break; } } return sampgdk::InvokeNative( Native, function_format.c_str( ), data, format, args ... ); } }; };
Plugins::SSCANF::unformat( "Data 5.0 hello", "p< >s[5]fs[6]", varstring1, &varfloat, varstring2 );
I worked around these things, with help from your responses (thanks !) and now I came back with additional things:
|
if (amx_FindPublic(amx, query->Callback.Name.c_str(), &amx_index) == AMX_ERR_NONE && amx_index >= 0)
if (!amx_FindPublic(amx, query->Callback.Name.c_str(), &amx_index))
CError<CHandle> handle_error; Handle_t handle = CHandleManager::Get()->Create( "localhost", "root", "pass", "database", options, handle_error); if (handle_error) { // some error happened return 0; } Query_t query = CQuery::Create("SELECT * FROM stuff"); query->OnExecutionFinished([callback](ResultSet_t resultset) { Result_t result = resultset->GetActiveResult(); std::string stuff; result->GetRowDataByName(0, "fieldname", stuff); printf("stuff is %s\n", stuff.c_str()); }); handle->Execute(CHandle::ExecutionType::PARALLEL, query);
Hello,
I want to leave a response here about Streamer with SAMPGDK. You can use it as xeeZ said here, but you don't need to invoke Streamer_CallbackHook since it is deprecated in version 2.7.8. Why? Because Incognito decided to use SAMPGDK for OnPlayerConnect and OnPlayerDisconnect. All you need to do is to invoke CreateDynamicObject as xeeZ do in his gist. Code:
int CreateDynamicObject(int modelid, float x, float y, float z, float rx, float ry, float rz, int worldid = -1, int interiorid = -1, int playerid = -1, float streamdistance = 200.0, float drawdistance = 0.0) { static AMX_NATIVE native = sampgdk::FindNative("CreateDynamicObject"); return sampgdk::InvokeNative(native, "iffffffiiiff", modelid, x, y, z, rx, ry, rz, worldid, interiorid, playerid, streamdistance, drawdistance); } Now, I want to know your opinion. If we want to use Streamer with SAMPGDK it is better to invoke a native (like the method above) or to combine streamer plugin with our project (which will be a pain in the a** with plugin updates and with the combination)? By the way, can we register a Streamer's callback in our plugins? I tried this Code:
SAMPGDK_CALLBACK(bool, OnPlayerEditDynamicObject(int playerid, int objectid, int response, float x, float y, float z, float rx, float ry, float rz)); SAMPGDK_CALLBACK(bool, OnPlayerSelectDynamicObject(int playerid, int objectid, int modelid, float x, float y, float z)); PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerEditDynamicObject(int playerid, int objectid, int response, float x, float y, float z, float rx, float ry, float rz) { sampgdk::logprintf("OnPlayerEditDynamicObject: %i | %f | %f | %f", objectid, x, y, z); return true; } PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerSelectDynamicObject(int playerid, int objectid, int modelid, float x, float y, float z) { sampgdk::logprintf("OnPlayerSelectDynamicObject: %i | %f | %f | %f", objectid, x, y, z); return true; } |
https://github.com/IstuntmanI/samp-s...sampgdk-invoke for streamer (or just port it).
sscanf is already supplied in C. mxINI... create your own INI parser or find one on github, there's tons. |