Skip to content

Instantly share code, notes, and snippets.

@Zeex
Last active December 15, 2015 06:39
Show Gist options
  • Save Zeex/5217723 to your computer and use it in GitHub Desktop.
Save Zeex/5217723 to your computer and use it in GitHub Desktop.
CallNative()
#include <cstring>
#include <sampgdk/amx.h>
#include <sampgdk/core.h>
cell CallNative(AMX *amx, AMX_NATIVE native, int num_params) {
int params_size = num_params * sizeof(cell);
amx_Push(amx, params_size);
cell *params;
amx_GetAddr(amx, amx->stk, &params);
amx->paramcount = 0;
cell retval = native(amx, params);
amx->stk += params_size + sizeof(cell);
return retval;
}
AMX_NATIVE FindNative(const char *name) {
const AMX_NATIVE_INFO *natives = sampgdk_get_natives();
int num_natives = sampgdk_num_natives();
for (int i = 0; i < num_natives; i++) {
if (std::strcmp(natives[i].name, name) == 0) {
return natives[i].func;
}
}
return 0;
}
#ifndef CALLNATIVE_H
#define CALLNATIVE_H
#include <sampgdk/amx.h>
template<typename T>
class NativeArgument {
public:
NativeArgument(AMX *amx, cell x) {
amx_Push(amx, x);
}
};
template<>
class NativeArgument<float> {
public:
NativeArgument(AMX *amx, float x) {
amx_Push(amx, amx_ftoc(x));
}
};
template<>
class NativeArgument<const char *> {
public:
NativeArgument(AMX *amx, const char *s): amx_(amx) {
amx_PushString(amx, &address_, 0, s, 0, 0);
}
~NativeArgument() {
amx_Release(amx_, address_);
}
private:
AMX *amx_;
cell address_;
};
template<>
class NativeArgument<std::string> {
public:
NativeArgument(AMX *amx, std::string s) : amx_(amx) {
amx_PushString(amx, &address_, 0, s.c_str(), 0, 0);
}
~NativeArgument() {
amx_Release(amx_, address_);
}
private:
AMX *amx_;
cell address_;
};
template<typename T = cell>
struct ConvertCell {
static cell Convert(cell x) { return x; }
};
template<>
struct ConvertCell<bool> {
static bool Convert(cell x) { return x != 0; }
};
template<>
struct ConvertCell<float> {
static float Convert(cell x) { return amx_ctof(x); }
};
template<>
struct ConvertCell<void> {
static cell Convert(cell x) { return 0; }
};
cell CallNative(AMX *amx, AMX_NATIVE native, int num_params);
template<typename R>
R DoCallNative(AMX *amx, AMX_NATIVE native, int num_params) {
return ConvertCell<R>::Convert(CallNative(amx, native, num_params));
}
template<typename R>
R CallNative(AMX *amx, AMX_NATIVE native) {
return DoCallNative<R>(amx, native, 0);
}
template<typename R, typename T1>
R CallNative(AMX *amx, AMX_NATIVE native, T1 x1) {
NativeArgument<T1> a1(amx, x1);
return DoCallNative<R>(amx, native, 1);
}
template<typename R, typename T1, typename T2>
R CallNative(AMX *amx, AMX_NATIVE native, T1 x1, T2 x2) {
NativeArgument<T2> a2(amx, x2);
NativeArgument<T1> a1(amx, x1);
return DoCallNative<R>(amx, native, 2);
}
template<typename R, typename T1, typename T2, typename T3>
R CallNative(AMX *amx, AMX_NATIVE native, T1 x1, T2 x2, T3 x3) {
NativeArgument<T3> a3(amx, x3);
NativeArgument<T2> a2(amx, x2);
NativeArgument<T1> a1(amx, x1);
return DoCallNative<R>(amx, native, 3);
}
template<typename R, typename T1, typename T2, typename T3, typename T4>
R CallNative(AMX *amx, AMX_NATIVE native, T1 x1, T2 x2, T3 x3, T4 x4) {
NativeArgument<T4> a4(amx, x4);
NativeArgument<T3> a3(amx, x3);
NativeArgument<T2> a2(amx, x2);
NativeArgument<T1> a1(amx, x1);
return DoCallNative<R>(amx, native, 4);
}
template<typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
R CallNative(AMX *amx, AMX_NATIVE native, T1 x1, T2 x2, T3 x3, T4 x4, T5 x5) {
NativeArgument<T5> a5(amx, x5);
NativeArgument<T4> a4(amx, x4);
NativeArgument<T3> a3(amx, x3);
NativeArgument<T2> a2(amx, x2);
NativeArgument<T1> a1(amx, x1);
return DoCallNative<R>(amx, native, 5);
}
template<typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
R CallNative(AMX *amx, AMX_NATIVE native, T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6) {
NativeArgument<T6> a6(amx, x6);
NativeArgument<T5> a5(amx, x5);
NativeArgument<T4> a4(amx, x4);
NativeArgument<T3> a3(amx, x3);
NativeArgument<T2> a2(amx, x2);
NativeArgument<T1> a1(amx, x1);
return DoCallNative<R>(amx, native, 6);
}
template<typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
R CallNative(AMX *amx, AMX_NATIVE native, T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7) {
NativeArgument<T7> a7(amx, x7);
NativeArgument<T6> a6(amx, x6);
NativeArgument<T5> a5(amx, x5);
NativeArgument<T4> a4(amx, x4);
NativeArgument<T3> a3(amx, x3);
NativeArgument<T2> a2(amx, x2);
NativeArgument<T1> a1(amx, x1);
return DoCallNative<R>(amx, native, 7);
}
template<typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
R CallNative(AMX *amx, AMX_NATIVE native, T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, T8 x8) {
NativeArgument<T8> a8(amx, x8);
NativeArgument<T7> a7(amx, x7);
NativeArgument<T6> a6(amx, x6);
NativeArgument<T5> a5(amx, x5);
NativeArgument<T4> a4(amx, x4);
NativeArgument<T3> a3(amx, x3);
NativeArgument<T2> a2(amx, x2);
NativeArgument<T1> a1(amx, x1);
return DoCallNative<R>(amx, native, 8);
}
template<typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
R CallNative(AMX *amx, AMX_NATIVE native, T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, T8 x8, T9 x9) {
NativeArgument<T9> a9(amx, x8);
NativeArgument<T8> a8(amx, x8);
NativeArgument<T7> a7(amx, x7);
NativeArgument<T6> a6(amx, x6);
NativeArgument<T5> a5(amx, x5);
NativeArgument<T4> a4(amx, x4);
NativeArgument<T3> a3(amx, x3);
NativeArgument<T2> a2(amx, x2);
NativeArgument<T1> a1(amx, x1);
return DoCallNative<R>(amx, native, 9);
}
AMX_NATIVE FindNative(const char *name);
#endif // !CALLNATIVE_H
#include "callnative.h"
#include "fakeamx.h"
bool MySendClientMessage(int playerid, int color, const char *message) {
static AMX_NATIVE native = FindNative("SendClientMessage");
return CallNative<bool>(FakeAmx::Instance().amx(), native, playerid, 0x0000FFFF, message);
}
#include <cstring>
#include <limits>
#include "fakeamx.h"
static const std::size_t INITIAL_HEAP_SIZE = 1024;
FakeAmx &FakeAmx::Instance() {
static FakeAmx instance;
return instance;
}
FakeAmx::FakeAmx():
heap_(INITIAL_HEAP_SIZE)
{
std::memset(&hdr_, 0, sizeof(hdr_));
std::memset(&amx_, 0, sizeof(amx_));
hdr_.magic = AMX_MAGIC;
hdr_.file_version = MIN_FILE_VERSION;
hdr_.amx_version = MIN_AMX_VERSION;
hdr_.dat = reinterpret_cast<int32_t>(&heap_[0]) -
reinterpret_cast<int32_t>(&hdr_);
amx_.base = reinterpret_cast<unsigned char*>(&hdr_);
amx_.data = reinterpret_cast<unsigned char*>(&heap_[0]);
amx_.callback = amx_Callback;
amx_.stp = std::numeric_limits<cell>::max();
amx_.error = AMX_ERR_NONE;
}
FakeAmx::~FakeAmx() {
}
AMX *FakeAmx::amx() {
return &amx_;
}
const AMX *FakeAmx::amx() const {
return &amx_;
}
cell FakeAmx::Push(std::size_t cells) {
cell address = amx_.hea;
amx_.hea += cells * sizeof(cell);
if (amx_.hea/sizeof(cell) >= static_cast<cell>(heap_.size())) {
heap_.resize(amx_.hea/sizeof(cell));
}
return address;
}
cell FakeAmx::Push(const char *s) {
std::size_t size = std::strlen(s) + 1;
cell address = Push(size);
amx_SetString(&heap_[0] + address/sizeof(cell), s, 0, 0, size);
return address;
}
void FakeAmx::GetData(cell address, cell &value) const {
value = heap_[address/sizeof(cell)];
}
void FakeAmx::GetData(cell address, char *value, std::size_t size) const {
const cell *ptr = &heap_[0] + address/sizeof(cell);
amx_GetString(value, ptr, 0, size);
}
void FakeAmx::Pop(cell address) {
if (amx_.hea > address) {
amx_.hea = address;
}
}
cell FakeAmx::CallNative(AMX_NATIVE native, cell *params) {
return native(&amx_, params);
}
bool FakeAmx::CallBooleanNative(AMX_NATIVE native, cell *params) {
return CallNative(native, params) != 0;
}
FakeAmxHeapObject::FakeAmxHeapObject(FakeAmx &fa):
fa_(fa),
size_(1),
address_(fa.Push(1))
{
}
FakeAmxHeapObject::FakeAmxHeapObject(FakeAmx &fa, std::size_t cells):
fa_(fa),
size_(cells),
address_(fa.Push(cells))
{
}
FakeAmxHeapObject::FakeAmxHeapObject(FakeAmx &fa, const char *s):
fa_(fa),
size_(std::strlen(s) + 1),
address_(fa.Push(s))
{
}
FakeAmxHeapObject::~FakeAmxHeapObject() {
fa_.Pop(address_);
}
cell FakeAmxHeapObject::address() const {
return address_;
}
std::size_t FakeAmxHeapObject::size() const {
return size_;
}
cell FakeAmxHeapObject::GetAsCell() const {
cell value;
fa_.GetData(address_, value);
return value;
}
bool FakeAmxHeapObject::GetAsBool() const {
return GetAsCell() != 0;
}
float FakeAmxHeapObject::GetAsFloat() const {
cell value = this->GetAsCell();
return amx_ctof(value);
}
void FakeAmxHeapObject::GetAsString(char *s, std::size_t size) const {
fa_.GetData(address_, s, size);
}
#ifndef FAKEAMX_H
#define FAKEAMX_H
#include <cstddef>
#include <vector>
#include <sampgdk/amx.h>
class FakeAmx {
public:
static FakeAmx &Instance();
~FakeAmx();
AMX *amx();
const AMX *amx() const;
cell Push(std::size_t cells);
cell Push(const char *s);
void GetData(cell address, cell &value) const;
void GetData(cell address, char *value, std::size_t size) const;
void Pop(cell address);
cell CallNative(AMX_NATIVE native, cell *params);
bool CallBooleanNative(AMX_NATIVE native, cell *params);
private:
FakeAmx();
FakeAmx(const FakeAmx &);
void operator=(const FakeAmx &);
private:
AMX amx_;
AMX_HEADER hdr_;
std::vector<cell> heap_;
};
class FakeAmxHeapObject {
public:
FakeAmxHeapObject(FakeAmx &fa);
FakeAmxHeapObject(FakeAmx &fa, std::size_t cells);
FakeAmxHeapObject(FakeAmx &fa, const char *s);
~FakeAmxHeapObject();
cell address() const;
std::size_t size() const;
cell GetAsCell() const;
bool GetAsBool() const;
float GetAsFloat() const;
void GetAsString(char *s, std::size_t size) const;
private:
FakeAmxHeapObject(const FakeAmxHeapObject &);
void operator=(const FakeAmxHeapObject &);
private:
FakeAmx &fa_;
cell address_;
std::size_t size_;
};
#endif // !FAKEAMX_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment