簡體   English   中英

如何在編譯時或代碼初始化時自動更新數組中的條目?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM