Added the ability for extensions to invoke arbitrary natives (bug 3605, r=ds,theY4Kman).
1.1 --- a/core/Makefile Sat Jan 31 22:51:48 2009 -0500
1.2 +++ b/core/Makefile Sun Feb 01 02:03:03 2009 -0500
1.3 @@ -33,7 +33,8 @@
1.4 LibrarySys.cpp \
1.5 PluginInfoDatabase.cpp \
1.6 PluginSys.cpp \
1.7 - ShareSys.cpp
1.8 + ShareSys.cpp \
1.9 + NativeInvoker.cpp
1.10 OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
1.11
1.12 ##############################################
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/core/NativeInvoker.cpp Sun Feb 01 02:03:03 2009 -0500
2.3 @@ -0,0 +1,379 @@
2.4 +/**
2.5 + * vim: set ts=4 :
2.6 + * =============================================================================
2.7 + * SourcePawn
2.8 + * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
2.9 + * =============================================================================
2.10 + *
2.11 + * This program is free software; you can redistribute it and/or modify it under
2.12 + * the terms of the GNU General Public License, version 3.0, as published by the
2.13 + * Free Software Foundation.
2.14 + *
2.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
2.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2.18 + * details.
2.19 + *
2.20 + * You should have received a copy of the GNU General Public License along with
2.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
2.22 + *
2.23 + * As a special exception, AlliedModders LLC gives you permission to link the
2.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
2.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
2.26 + * by the Valve Corporation. You must obey the GNU General Public License in
2.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
2.28 + * this exception to all derivative works. AlliedModders LLC defines further
2.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
2.30 + * or <http://www.sourcemod.net/license.php>.
2.31 + *
2.32 + * Version: $Id$
2.33 + */
2.34 +
2.35 +#include "NativeInvoker.h"
2.36 +#include "ShareSys.h"
2.37 +
2.38 +NativeInterface g_NInvoke;
2.39 +
2.40 +NativeInvoker::NativeInvoker()
2.41 +{
2.42 +}
2.43 +
2.44 +NativeInvoker::~NativeInvoker()
2.45 +{
2.46 +}
2.47 +
2.48 +const char *NativeInterface::GetInterfaceName()
2.49 +{
2.50 + return SMINTERFACE_NINVOKE_NAME;
2.51 +}
2.52 +
2.53 +unsigned int NativeInterface::GetInterfaceVersion()
2.54 +{
2.55 + return SMINTERFACE_NINVOKE_VERSION;
2.56 +}
2.57 +
2.58 +void NativeInterface::OnSourceModAllInitialized()
2.59 +{
2.60 + g_ShareSys.AddInterface(NULL, &g_NInvoke);
2.61 +}
2.62 +
2.63 +IPluginRuntime *NativeInterface::CreateRuntime(const char *name, size_t bytes)
2.64 +{
2.65 + return g_pSourcePawn2->CreateEmptyRuntime(name, bytes);
2.66 +}
2.67 +
2.68 +INativeInvoker *NativeInterface::CreateInvoker()
2.69 +{
2.70 + return new NativeInvoker();
2.71 +}
2.72 +
2.73 +bool NativeInvoker::Start(IPluginContext *pContext, const char *name)
2.74 +{
2.75 + NativeEntry *entry;
2.76 +
2.77 + entry = g_ShareSys.FindNative(name);
2.78 + if (entry == NULL)
2.79 + {
2.80 + return false;
2.81 + }
2.82 +
2.83 + native = NULL;
2.84 + if (entry->replacement.owner != NULL)
2.85 + {
2.86 + native = entry->replacement.func;
2.87 + }
2.88 + else if (entry->owner != NULL)
2.89 + {
2.90 + native = entry->func;
2.91 + }
2.92 +
2.93 + if (native == NULL)
2.94 + {
2.95 + return false;
2.96 + }
2.97 +
2.98 + this->pContext = pContext;
2.99 +
2.100 + m_curparam = 0;
2.101 + m_errorstate = SP_ERROR_NONE;
2.102 +
2.103 + return true;
2.104 +}
2.105 +
2.106 +cell_t NativeInvoker::PushCell(cell_t cell)
2.107 +{
2.108 + if (m_curparam >= SP_MAX_EXEC_PARAMS)
2.109 + {
2.110 + return SetError(SP_ERROR_PARAMS_MAX);
2.111 + }
2.112 +
2.113 + m_info[m_curparam].marked = false;
2.114 + m_params[m_curparam] = cell;
2.115 + m_curparam++;
2.116 +
2.117 + return SP_ERROR_NONE;
2.118 +}
2.119 +
2.120 +int NativeInvoker::PushCellByRef(cell_t *cell, int flags)
2.121 +{
2.122 + return PushArray(cell, 1, flags);
2.123 +}
2.124 +
2.125 +int NativeInvoker::PushFloat(float number)
2.126 +{
2.127 + cell_t val = *(cell_t *)&number;
2.128 +
2.129 + return PushCell(val);
2.130 +}
2.131 +
2.132 +int NativeInvoker::PushFloatByRef(float *number, int flags)
2.133 +{
2.134 + return PushCellByRef((cell_t *)number, flags);
2.135 +}
2.136 +
2.137 +int NativeInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback)
2.138 +{
2.139 + if (m_curparam >= SP_MAX_EXEC_PARAMS)
2.140 + {
2.141 + return SetError(SP_ERROR_PARAMS_MAX);
2.142 + }
2.143 +
2.144 + ParamInfo *info = &m_info[m_curparam];
2.145 +
2.146 + info->flags = inarray ? copyback : 0;
2.147 + info->marked = true;
2.148 + info->size = cells;
2.149 + info->str.is_sz = false;
2.150 + info->orig_addr = inarray;
2.151 +
2.152 + m_curparam++;
2.153 +
2.154 + return SP_ERROR_NONE;
2.155 +}
2.156 +
2.157 +int NativeInvoker::PushString(const char *string)
2.158 +{
2.159 + return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
2.160 +}
2.161 +
2.162 +int NativeInvoker::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
2.163 +{
2.164 + return _PushString(buffer, sz_flags, cp_flags, length);
2.165 +}
2.166 +
2.167 +int NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
2.168 +{
2.169 + if (m_curparam >= SP_MAX_EXEC_PARAMS)
2.170 + {
2.171 + return SetError(SP_ERROR_PARAMS_MAX);
2.172 + }
2.173 +
2.174 + ParamInfo *info = &m_info[m_curparam];
2.175 +
2.176 + info->marked = true;
2.177 + info->orig_addr = (cell_t *)string;
2.178 + info->flags = cp_flags;
2.179 + info->size = len;
2.180 + info->str.sz_flags = sz_flags;
2.181 + info->str.is_sz = true;
2.182 +
2.183 + m_curparam++;
2.184 +
2.185 + return SP_ERROR_NONE;
2.186 +}
2.187 +
2.188 +void NativeInvoker::Cancel()
2.189 +{
2.190 + if (pContext == NULL)
2.191 + {
2.192 + return;
2.193 + }
2.194 +
2.195 + m_errorstate = SP_ERROR_NONE;
2.196 + m_curparam = 0;
2.197 + pContext = NULL;
2.198 + native = NULL;
2.199 +}
2.200 +
2.201 +int NativeInvoker::SetError(int err)
2.202 +{
2.203 + m_errorstate = err;
2.204 + return err;
2.205 +}
2.206 +
2.207 +int NativeInvoker::Invoke(cell_t *result)
2.208 +{
2.209 + int err = SP_ERROR_NONE;
2.210 +
2.211 + if (pContext == NULL)
2.212 + {
2.213 + return SP_ERROR_INVALID_NATIVE;
2.214 + }
2.215 +
2.216 + if (m_errorstate != SP_ERROR_NONE)
2.217 + {
2.218 + err = m_errorstate;
2.219 + Cancel();
2.220 + return err;
2.221 + }
2.222 +
2.223 + cell_t tresult;
2.224 +
2.225 + if (result == NULL)
2.226 + {
2.227 + result = &tresult;
2.228 + }
2.229 +
2.230 + //This is for re-entrancy!
2.231 + IPluginContext *ctx = pContext;
2.232 + cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1];
2.233 + cell_t *temp_params = &_temp_params[1];
2.234 + ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
2.235 + unsigned int numparams = m_curparam;
2.236 + unsigned int i;
2.237 + bool docopies = true;
2.238 +
2.239 + if (numparams)
2.240 + {
2.241 + //Save the info locally, then reset it for re-entrant calls.
2.242 + memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
2.243 + }
2.244 + m_curparam = 0;
2.245 + pContext = NULL;
2.246 +
2.247 + /* Initialize 0th parameter */
2.248 + _temp_params[0] = numparams;
2.249 +
2.250 + /* Browse the parameters and build arrays */
2.251 + for (i = 0; i < numparams; i++)
2.252 + {
2.253 + /* Is this marked as an array? */
2.254 + if (temp_info[i].marked)
2.255 + {
2.256 + if (!temp_info[i].str.is_sz)
2.257 + {
2.258 + /* Allocate a normal/generic array */
2.259 + if ((err = ctx->HeapAlloc(temp_info[i].size,
2.260 + &temp_info[i].local_addr,
2.261 + &temp_info[i].phys_addr))
2.262 + != SP_ERROR_NONE)
2.263 + {
2.264 + break;
2.265 + }
2.266 + if (temp_info[i].orig_addr)
2.267 + {
2.268 + memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size);
2.269 + }
2.270 + }
2.271 + else
2.272 + {
2.273 + /* Calculate cells required for the string */
2.274 + size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
2.275 +
2.276 + /* Allocate the buffer */
2.277 + if ((err = ctx->HeapAlloc(cells,
2.278 + &temp_info[i].local_addr,
2.279 + &temp_info[i].phys_addr))
2.280 + != SP_ERROR_NONE)
2.281 + {
2.282 + break;
2.283 + }
2.284 + /* Copy original string if necessary */
2.285 + if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL))
2.286 + {
2.287 + /* Cut off UTF-8 properly */
2.288 + if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
2.289 + {
2.290 + if ((err = ctx->StringToLocalUTF8(temp_info[i].local_addr,
2.291 + temp_info[i].size,
2.292 + (const char *)temp_info[i].orig_addr,
2.293 + NULL))
2.294 + != SP_ERROR_NONE)
2.295 + {
2.296 + break;
2.297 + }
2.298 + }
2.299 + /* Copy a binary blob */
2.300 + else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY)
2.301 + {
2.302 + memmove(temp_info[i].phys_addr, temp_info[i].orig_addr, temp_info[i].size);
2.303 + }
2.304 + /* Copy ASCII characters */
2.305 + else
2.306 + {
2.307 + if ((err = ctx->StringToLocal(temp_info[i].local_addr,
2.308 + temp_info[i].size,
2.309 + (const char *)temp_info[i].orig_addr))
2.310 + != SP_ERROR_NONE)
2.311 + {
2.312 + break;
2.313 + }
2.314 + }
2.315 + }
2.316 + } /* End array/string calculation */
2.317 + /* Update the pushed parameter with the byref local address */
2.318 + temp_params[i] = temp_info[i].local_addr;
2.319 + }
2.320 + else
2.321 + {
2.322 + /* Just copy the value normally */
2.323 + temp_params[i] = m_params[i];
2.324 + }
2.325 + }
2.326 +
2.327 + /* Make the call if we can */
2.328 + if (err == SP_ERROR_NONE)
2.329 + {
2.330 + *result = native(ctx, _temp_params);
2.331 + if (ctx->GetLastNativeError() != SP_ERROR_NONE)
2.332 + {
2.333 + docopies = false;
2.334 + ctx->ClearLastNativeError();
2.335 + }
2.336 + }
2.337 + else
2.338 + {
2.339 + docopies = false;
2.340 + }
2.341 +
2.342 + /* i should be equal to the last valid parameter + 1 */
2.343 + while (i--)
2.344 + {
2.345 + if (!temp_info[i].marked)
2.346 + {
2.347 + continue;
2.348 + }
2.349 +
2.350 + if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK))
2.351 + {
2.352 + if (temp_info[i].orig_addr)
2.353 + {
2.354 + if (temp_info[i].str.is_sz)
2.355 + {
2.356 + memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size);
2.357 +
2.358 + }
2.359 + else
2.360 + {
2.361 + if (temp_info[i].size == 1)
2.362 + {
2.363 + *temp_info[i].orig_addr = *(temp_info[i].phys_addr);
2.364 + }
2.365 + else
2.366 + {
2.367 + memcpy(temp_info[i].orig_addr,
2.368 + temp_info[i].phys_addr,
2.369 + temp_info[i].size * sizeof(cell_t));
2.370 + }
2.371 + }
2.372 + }
2.373 + }
2.374 +
2.375 + if ((err = ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
2.376 + {
2.377 + return err;
2.378 + }
2.379 + }
2.380 +
2.381 + return err;
2.382 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/core/NativeInvoker.h Sun Feb 01 02:03:03 2009 -0500
3.3 @@ -0,0 +1,98 @@
3.4 +/**
3.5 + * vim: set ts=4 :
3.6 + * =============================================================================
3.7 + * SourceMod
3.8 + * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
3.9 + * =============================================================================
3.10 + *
3.11 + * This program is free software; you can redistribute it and/or modify it under
3.12 + * the terms of the GNU General Public License, version 3.0, as published by the
3.13 + * Free Software Foundation.
3.14 + *
3.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
3.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
3.18 + * details.
3.19 + *
3.20 + * You should have received a copy of the GNU General Public License along with
3.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
3.22 + *
3.23 + * As a special exception, AlliedModders LLC gives you permission to link the
3.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
3.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
3.26 + * by the Valve Corporation. You must obey the GNU General Public License in
3.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
3.28 + * this exception to all derivative works. AlliedModders LLC defines further
3.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
3.30 + * or <http://www.sourcemod.net/license.php>.
3.31 + *
3.32 + * Version: $Id$
3.33 + */
3.34 +
3.35 +#ifndef _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
3.36 +#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
3.37 +
3.38 +#include "sm_globals.h"
3.39 +#include <INativeInvoker.h>
3.40 +
3.41 +struct ParamInfo
3.42 +{
3.43 + int flags; /* Copy-back flags */
3.44 + bool marked; /* Whether this is marked as being used */
3.45 + cell_t local_addr; /* Local address to free */
3.46 + cell_t *phys_addr; /* Physical address of our copy */
3.47 + cell_t *orig_addr; /* Original address to copy back to */
3.48 + ucell_t size; /* Size of array in bytes */
3.49 + struct
3.50 + {
3.51 + bool is_sz; /* is a string */
3.52 + int sz_flags; /* has sz flags */
3.53 + } str;
3.54 +};
3.55 +
3.56 +class NativeInvoker : public INativeInvoker
3.57 +{
3.58 +public:
3.59 + NativeInvoker();
3.60 + ~NativeInvoker();
3.61 +public: /* ICallable */
3.62 + int PushCell(cell_t cell);
3.63 + int PushCellByRef(cell_t *cell, int flags=SM_PARAM_COPYBACK);
3.64 + int PushFloat(float number);
3.65 + int PushFloatByRef(float *number, int flags=SM_PARAM_COPYBACK);
3.66 + int PushArray(cell_t *inarray, unsigned int cells, int flags=0);
3.67 + int PushString(const char *string);
3.68 + int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
3.69 + void Cancel();
3.70 +public: /* INativeInvoker */
3.71 + bool Start(IPluginContext *pContext, const char *name);
3.72 + int Invoke(cell_t *result);
3.73 +private:
3.74 + int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
3.75 + int SetError(int err);
3.76 +private:
3.77 + IPluginContext *pContext;
3.78 + SPVM_NATIVE_FUNC native;
3.79 + cell_t m_params[SP_MAX_EXEC_PARAMS];
3.80 + ParamInfo m_info[SP_MAX_EXEC_PARAMS];
3.81 + unsigned int m_curparam;
3.82 + int m_errorstate;
3.83 +};
3.84 +
3.85 +class NativeInterface :
3.86 + public INativeInterface,
3.87 + public SMGlobalClass
3.88 +{
3.89 +public: /* SMGlobalClass */
3.90 + void OnSourceModAllInitialized();
3.91 +public: /* SMInterface */
3.92 + unsigned int GetInterfaceVersion();
3.93 + const char *GetInterfaceName();
3.94 +public: /* INativeInvoker */
3.95 + IPluginRuntime *CreateRuntime(const char *name, size_t bytes);
3.96 + INativeInvoker *CreateInvoker();
3.97 +};
3.98 +
3.99 +extern NativeInterface g_NInvoke;
3.100 +
3.101 +#endif /* _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_ */
4.1 --- a/core/ShareSys.h Sat Jan 31 22:51:48 2009 -0500
4.2 +++ b/core/ShareSys.h Sun Feb 01 02:03:03 2009 -0500
4.3 @@ -128,10 +128,10 @@
4.4 void BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly);
4.5 void BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry);
4.6 NativeEntry *AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
4.7 + NativeEntry *FindNative(const char *name);
4.8 private:
4.9 NativeEntry *AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv);
4.10 void ClearNativeFromCache(CNativeOwner *pOwner, const char *name);
4.11 - NativeEntry *FindNative(const char *name);
4.12 void BindNativeToPlugin(CPlugin *pPlugin,
4.13 sp_native_t *ntv,
4.14 uint32_t index,
5.1 --- a/core/msvc9/sourcemod_mm.vcproj Sat Jan 31 22:51:48 2009 -0500
5.2 +++ b/core/msvc9/sourcemod_mm.vcproj Sun Feb 01 02:03:03 2009 -0500
5.3 @@ -1186,6 +1186,10 @@
5.4 >
5.5 </File>
5.6 <File
5.7 + RelativePath="..\NativeInvoker.cpp"
5.8 + >
5.9 + </File>
5.10 + <File
5.11 RelativePath="..\NativeOwner.cpp"
5.12 >
5.13 </File>
5.14 @@ -1392,6 +1396,10 @@
5.15 >
5.16 </File>
5.17 <File
5.18 + RelativePath="..\NativeInvoker.h"
5.19 + >
5.20 + </File>
5.21 + <File
5.22 RelativePath="..\NativeOwner.h"
5.23 >
5.24 </File>
5.25 @@ -1557,6 +1565,10 @@
5.26 >
5.27 </File>
5.28 <File
5.29 + RelativePath="..\..\public\INativeInvoker.h"
5.30 + >
5.31 + </File>
5.32 + <File
5.33 RelativePath="..\..\public\IPlayerHelpers.h"
5.34 >
5.35 </File>
6.1 --- a/core/sourcemod.cpp Sat Jan 31 22:51:48 2009 -0500
6.2 +++ b/core/sourcemod.cpp Sun Feb 01 02:03:03 2009 -0500
6.3 @@ -200,7 +200,7 @@
6.4 g_pSourcePawn = getv1();
6.5 g_pSourcePawn2 = getv2();
6.6
6.7 - if (g_pSourcePawn2->GetAPIVersion() < 2)
6.8 + if (g_pSourcePawn2->GetAPIVersion() < 3)
6.9 {
6.10 g_pSourcePawn2 = NULL;
6.11 if (error && maxlength)
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/public/INativeInvoker.h Sun Feb 01 02:03:03 2009 -0500
7.3 @@ -0,0 +1,106 @@
7.4 +/**
7.5 + * vim: set ts=4 :
7.6 + * =============================================================================
7.7 + * SourceMod
7.8 + * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
7.9 + * =============================================================================
7.10 + *
7.11 + * This program is free software; you can redistribute it and/or modify it under
7.12 + * the terms of the GNU General Public License, version 3.0, as published by the
7.13 + * Free Software Foundation.
7.14 + *
7.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
7.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
7.18 + * details.
7.19 + *
7.20 + * You should have received a copy of the GNU General Public License along with
7.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
7.22 + *
7.23 + * As a special exception, AlliedModders LLC gives you permission to link the
7.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
7.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
7.26 + * by the Valve Corporation. You must obey the GNU General Public License in
7.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
7.28 + * this exception to all derivative works. AlliedModders LLC defines further
7.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
7.30 + * or <http://www.sourcemod.net/license.php>.
7.31 + *
7.32 + * Version: $Id$
7.33 + */
7.34 +
7.35 +#ifndef _INCLUDE_SOURCEMOD_INATIVEINVOKER_H_
7.36 +#define _INCLUDE_SOURCEMOD_INATIVEINVOKER_H_
7.37 +
7.38 +/**
7.39 + * @file INativeInvoker.h
7.40 + * @brief Interface for invoking natives.
7.41 + */
7.42 +
7.43 +#include <IShareSys.h>
7.44 +
7.45 +#define SMINTERFACE_NINVOKE_NAME "INativeInterface"
7.46 +#define SMINTERFACE_NINVOKE_VERSION 1
7.47 +
7.48 +#define NINVOKE_DEFAULT_MEMORY 16384
7.49 +
7.50 +namespace SourceMod
7.51 +{
7.52 + class INativeInvoker : public SourcePawn::ICallable
7.53 + {
7.54 + public:
7.55 + /**
7.56 + * @brief Virtual destructor - use delete to free this.
7.57 + */
7.58 + virtual ~INativeInvoker()
7.59 + {
7.60 + }
7.61 + public:
7.62 + /**
7.63 + * @brief Begins a native call.
7.64 + *
7.65 + * During a call's preparation, no new calls may be started.
7.66 + *
7.67 + * @param pContext Context to invoke native under.
7.68 + * @param name Name of native.
7.69 + * @return True if native was found, false otherwise.
7.70 + */
7.71 + virtual bool Start(IPluginContext *pContext, const char *name) = 0;
7.72 +
7.73 + /**
7.74 + * @brief Invokes the native. The preparation state is cleared immediately, meaning that
7.75 + * this object can be re-used after or even from inside the native being called.
7.76 + *
7.77 + * @param result Optional pointer to retrieve a result.
7.78 + * @return SP_ERROR return code.
7.79 + */
7.80 + virtual int Invoke(cell_t *result) = 0;
7.81 + };
7.82 +
7.83 + /**
7.84 + * @brief Factory for dealing with native invocations.
7.85 + */
7.86 + class INativeInterface : public SMInterface
7.87 + {
7.88 + public:
7.89 + /**
7.90 + * @brief Creates a virtual plugin. This can be used as an environment to invoke natives.
7.91 + *
7.92 + * IPluginRuntime objects must be freed with the delete operator.
7.93 + *
7.94 + * @param name Name, or NULL for anonymous.
7.95 + * @param bytes Number of bytes for memory (NINVOKE_DEFAULT_MEMORY recommended).
7.96 + * @return New runtime, or NULL on failure.
7.97 + */
7.98 + virtual IPluginRuntime *CreateRuntime(const char *name, size_t bytes) = 0;
7.99 +
7.100 + /**
7.101 + * @brief Creates an object that can be used to invoke a single native code.
7.102 + *
7.103 + * @return New native invoker (free with delete).
7.104 + */
7.105 + virtual INativeInvoker *CreateInvoker() = 0;
7.106 + };
7.107 +}
7.108 +
7.109 +#endif /* _INCLUDE_SOURCEMOD_INATIVEINVOKER_H_ */
8.1 --- a/public/sample_ext/sdk/smsdk_config.h Sat Jan 31 22:51:48 2009 -0500
8.2 +++ b/public/sample_ext/sdk/smsdk_config.h Sun Feb 01 02:03:03 2009 -0500
8.3 @@ -76,5 +76,6 @@
8.4 //#define SMEXT_ENABLE_TEXTPARSERS
8.5 //#define SMEXT_ENABLE_USERMSGS
8.6 //#define SMEXT_ENABLE_TRANSLATOR
8.7 +//#define SMEXT_ENABLE_NINVOKE
8.8
8.9 #endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
9.1 --- a/public/sample_ext/sdk/smsdk_ext.cpp Sat Jan 31 22:51:48 2009 -0500
9.2 +++ b/public/sample_ext/sdk/smsdk_ext.cpp Sun Feb 01 02:03:03 2009 -0500
9.3 @@ -97,6 +97,9 @@
9.4 #if defined SMEXT_ENABLE_TRANSLATOR
9.5 ITranslator *translator = NULL;
9.6 #endif
9.7 +#if defined SMEXT_ENABLE_NINVOKE
9.8 +INativeInterface *ninvoke = NULL;
9.9 +#endif
9.10
9.11 /** Exports the main interface */
9.12 PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
10.1 --- a/public/sample_ext/sdk/smsdk_ext.h Sat Jan 31 22:51:48 2009 -0500
10.2 +++ b/public/sample_ext/sdk/smsdk_ext.h Sun Feb 01 02:03:03 2009 -0500
10.3 @@ -91,6 +91,9 @@
10.4 #if defined SMEXT_ENABLE_TRANSLATOR
10.5 #include <ITranslator.h>
10.6 #endif
10.7 +#if defined SMEXT_ENABLE_NINVOKE
10.8 +#include <INativeInvoker.h>
10.9 +#endif
10.10
10.11 #if defined SMEXT_CONF_METAMOD
10.12 #include <ISmmPlugin.h>
10.13 @@ -289,6 +292,9 @@
10.14 #if defined SMEXT_ENABLE_TRANSLATOR
10.15 extern ITranslator *translator;
10.16 #endif
10.17 +#if defined SMEXT_ENABLE_NINVOKE
10.18 +extern INativeInterface *ninvoke;
10.19 +#endif
10.20
10.21 #if defined SMEXT_CONF_METAMOD
10.22 PLUGIN_GLOBALVARS();
11.1 --- a/public/sourcepawn/sp_vm_api.h Sat Jan 31 22:51:48 2009 -0500
11.2 +++ b/public/sourcepawn/sp_vm_api.h Sun Feb 01 02:03:03 2009 -0500
11.3 @@ -42,7 +42,7 @@
11.4
11.5 /** SourcePawn Engine API Version */
11.6 #define SOURCEPAWN_ENGINE_API_VERSION 4
11.7 -#define SOURCEPAWN_ENGINE2_API_VERSION 2
11.8 +#define SOURCEPAWN_ENGINE2_API_VERSION 3
11.9
11.10 #if !defined SOURCEMOD_BUILD
11.11 #define SOURCEMOD_BUILD
11.12 @@ -876,6 +876,11 @@
11.13 * @return True on success, false on failure.
11.14 */
11.15 virtual bool GetKey(int k, void **value) =0;
11.16 +
11.17 + /**
11.18 + * @brief Clears the last native error.
11.19 + */
11.20 + virtual void ClearLastNativeError() =0;
11.21 };
11.22
11.23
11.24 @@ -1252,6 +1257,15 @@
11.25 * Initialize() succeeded.
11.26 */
11.27 virtual void Shutdown() =0;
11.28 +
11.29 + /**
11.30 + * @brief Creates an empty plugin with a blob of memory.
11.31 + *
11.32 + * @param name Name, for debugging (NULL for anonymous).
11.33 + * @param bytes Number of bytes of memory (hea+stk).
11.34 + * @return New runtime, or NULL if not enough memory.
11.35 + */
11.36 + virtual IPluginRuntime *CreateEmptyRuntime(const char *name, uint32_t memory) =0;
11.37 };
11.38 };
11.39
12.1 --- a/sourcepawn/jit/BaseRuntime.cpp Sat Jan 31 22:51:48 2009 -0500
12.2 +++ b/sourcepawn/jit/BaseRuntime.cpp Sun Feb 01 02:03:03 2009 -0500
12.3 @@ -535,3 +535,21 @@
12.4
12.5 return m_NumFuncs;
12.6 }
12.7 +
12.8 +int BaseRuntime::CreateBlank(uint32_t heastk)
12.9 +{
12.10 + memset(m_pPlugin, 0, sizeof(sp_plugin_t));
12.11 +
12.12 + /* Align to cell_t bytes */
12.13 + heastk += sizeof(cell_t);
12.14 + heastk -= heastk % sizeof(cell_t);
12.15 +
12.16 + m_pPlugin->mem_size = heastk;
12.17 + m_pPlugin->memory = new uint8_t[heastk];
12.18 +
12.19 + m_pPlugin->profiler = g_engine2.GetProfiler();
12.20 + m_pCtx = new BaseContext(this);
12.21 + m_pCo = g_Jit.StartCompilation(this);
12.22 +
12.23 + return SP_ERROR_NONE;
12.24 +}
13.1 --- a/sourcepawn/jit/BaseRuntime.h Sat Jan 31 22:51:48 2009 -0500
13.2 +++ b/sourcepawn/jit/BaseRuntime.h Sun Feb 01 02:03:03 2009 -0500
13.3 @@ -27,6 +27,7 @@
13.4 BaseRuntime();
13.5 ~BaseRuntime();
13.6 public:
13.7 + virtual int CreateBlank(uint32_t heastk);
13.8 virtual int CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base);
13.9 virtual bool IsDebugging();
13.10 virtual IPluginDebugInfo *GetDebugInfo();
14.1 --- a/sourcepawn/jit/engine2.cpp Sat Jan 31 22:51:48 2009 -0500
14.2 +++ b/sourcepawn/jit/engine2.cpp Sun Feb 01 02:03:03 2009 -0500
14.3 @@ -191,3 +191,22 @@
14.4 {
14.5 g_Jit.ShutdownJIT();
14.6 }
14.7 +
14.8 +IPluginRuntime *SourcePawnEngine2::CreateEmptyRuntime(const char *name, uint32_t memory)
14.9 +{
14.10 + int err;
14.11 + BaseRuntime *rt;
14.12 +
14.13 + rt = new BaseRuntime();
14.14 + if ((err = rt->CreateBlank(memory)) != SP_ERROR_NONE)
14.15 + {
14.16 + delete rt;
14.17 + return NULL;
14.18 + }
14.19 +
14.20 + rt->m_pPlugin->name = strdup(name != NULL ? name : "<anonymous>");
14.21 +
14.22 + rt->ApplyCompilationOptions(NULL);
14.23 +
14.24 + return rt;
14.25 +}
15.1 --- a/sourcepawn/jit/engine2.h Sat Jan 31 22:51:48 2009 -0500
15.2 +++ b/sourcepawn/jit/engine2.h Sun Feb 01 02:03:03 2009 -0500
15.3 @@ -25,6 +25,7 @@
15.4 const char *GetErrorString(int err);
15.5 bool Initialize();
15.6 void Shutdown();
15.7 + IPluginRuntime *CreateEmptyRuntime(const char *name, uint32_t memory);
15.8 public:
15.9 IProfiler *GetProfiler();
15.10 private:
16.1 --- a/sourcepawn/jit/sp_vm_basecontext.cpp Sat Jan 31 22:51:48 2009 -0500
16.2 +++ b/sourcepawn/jit/sp_vm_basecontext.cpp Sun Feb 01 02:03:03 2009 -0500
16.3 @@ -873,3 +873,8 @@
16.4
16.5 return true;
16.6 }
16.7 +
16.8 +void BaseContext::ClearLastNativeError()
16.9 +{
16.10 + m_ctx.n_err = SP_ERROR_NONE;
16.11 +}
17.1 --- a/sourcepawn/jit/sp_vm_basecontext.h Sat Jan 31 22:51:48 2009 -0500
17.2 +++ b/sourcepawn/jit/sp_vm_basecontext.h Sun Feb 01 02:03:03 2009 -0500
17.3 @@ -93,6 +93,7 @@
17.4 void SetKey(int k, void *value);
17.5 bool GetKey(int k, void **value);
17.6 void Refresh();
17.7 + void ClearLastNativeError();
17.8 public:
17.9 bool IsInExec();
17.10 private: