[英]How to update entries in array automatically before/at compile time or code initialization time?
好吧,我有一個抽象的虛擬機(“ PAWN ”),它從我的代碼運行,腳本可以執行函數,這些函數從C代碼注冊到腳本,由我的C ++代碼執行。
c ++代碼必須以。的形式提供數組
{ "name_i_want_the_function_to_have_in_the_script" , function_in_my_cpp_code }
如果函數不在數組中,則無法執行。 (因為它不存在“)
所以這就把我們帶到了這個:
我的函數看起來像這樣:
//Pawn Functions
#define PWNFUNC(a) static cell AMX_NATIVE_CALL a(AMX *amx, cell *params)
namespace PawnFunc
{
PWNFUNC(GGV)
{
return pGameInterface->FindGameVersion();
}
};//namespace PawnFunc
帶有腳本函數信息的數組在另一個文件中,如下所示:
AMX_NATIVE_INFO custom_Natives[] =
{
{ "GetGameVersion", PawnFunc::GGV },
{ 0,0 }
};
現在的問題是:
是否有可能使該陣列自動更新? (在編譯時或編譯初始化時間之前)
至於現在我必須手動添加每個功能。 這有時很煩人,更容易出錯。
我想改變它,所以我可以這樣做:
//Pawn Functions
#define PWNFUNC(a,b) ...?...
namespace PawnFunc
{
PWNFUNC(GGV,GetGameVersion)//{ "GetGameVersion", PawnFunc::GGV }, is now added to "custom_Natives" array
{
return pGameInterface->FindGameVersion();
}
};//namespace PawnFunc
這有可能嗎? 如果是的話,我怎么能做到這一點?
也許有可能循環命名空間?
編輯:這里有一些偽代碼: http : //ideone.com/btG2lx
還有一個注意事項:我可以在運行時執行此操作,但必須在DLLMain完成(我的程序是DLL)。
如果您使用std::vector
作為腳本信息的存儲空間,那么#define
將完成這項工作。
(注意,該標准保證您仍然可以從&custom_Natives[0]
獲得C風格的數組)
std::vector<AMX_NATIVE_INFO> custom_Natives;
#define PWNFUNC(NAME, FUNC) \
struct IMPL_ ## FUNC { \
IMPL_ ## FUNC() { \
AMX_NATIVE_INFO entry = { NAME, PawnFunc::FUNC }; \
custom_Natives.push_back( entry ); \
} \
} INSTANCE_ ## FUNC; \
static cell AMX_NATIVE_CALL FUNC(AMX *amx, cell *params)
現在,這樣的代碼都將定義功能,並添加腳本條目custom_Natives
。
PWNFUNC("GetGameVersion", GGV)
{
return pGameInterface->FindGameVersion();
}
我能想出什么(假設C風格的數組和C-linkage功能):
AMX_NATIVE_INFO custom_natives[] =
{
{ "GetGameVersion", TheGGVFunc },
{ 0, 0 }
};
// here a function call named `GetGameVersion` was encountered,
// so let's look it up using a naive linear search
const char *toBeCalled = "GetGameVersion"; // obtain this somehow
void (*fptr)(void) = NULL;
for (int i = 0; i < sizeof(custom_natives) / sizeof(*custom_natives) - 1; i++) {
const char *name = custom_natives[i].name;
if (strcmp(toBeCalled, name) == 0) {
fptr = custom_natives[i].func;
break;
}
}
if (fptr != NULL) {
fptr();
}
你可以近似它; 我們的想法是使用全局std::vector
而不是C數組,並使用全局對象的構造函數來擴展向量。 這樣,你的數組將在main()
開始執行時初始化。 因此,您將擁有一個而不是custom_Natives
數組
std::vector<MethodArrayElementType> custom_Natives;
vector(將MethodArrayElementType
替換為包含字符串 - >函數指針映射的struct的名稱)。 您可以使用&custom_Natives[0]
將此向量視為普通C數組。
然后,在您定義的每個函數旁邊,添加一個Registrar
類來注冊該方法:
PWNFUNC(GGV) {
// Your implementation goes here...
}
struct GGV_Registrar {
GGV_Registrar() {
MethodArrayElementType e = { "GetGameVersion", GGV };
custom_Natives.push_back( e );
};
} GGV_Registrar_instance;
在調用main()
之前將調用全局GGV_Registrar_instance
構造函數的構造函數,它將更新custom_Natives
向量。
我們做這樣的事情,但我們使用鏈表而不是使用數組。 所以你的榜樣就會變成
namespace PawnFunc
{
PWNFUNC(GGV)
{
return pGameInterface->FindGameVersion();
}
PawnRegister GGVfunc( "GetGameVersion", GGV );
};//namespace PawnFunc
PawnRegister的構造函數將所有對象(如GVVfunc)添加到鏈接列表中。 當您的腳本引擎想要查找函數時,它會遍歷列表而不是掃描數組。 我想你可以設置PawnRegister來為數組添加條目。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.