我決定做的就是使插件接受一個簡單的接口:
DWORD func (LPARAM pBuf, DWORD size);
這將允許用戶在XML中指定的參數,然後定義他們希望我的結構通過他們,例如
typedef struct
{
int a;
float b;
double c;
wchar_t * d;
} test1;
當他們從我那裏得到這條消息時,他們可以在使用緩衝區之前檢查大小,以確保XML和結構匹配。
正如我解析XML,我使用這個類模板的方法來動態地構造對象:
class DynamicStructure
{
public:
template <typename T>
void addField(const T & field)
{
m_mapPtrSize.push_back(std::make_pair(reinterpret_cast<const LPARAM>(&field), sizeof(T)));
}
DWORD getSize()
{
//
// Work out the combined size of all the fields
DWORD sSize = 0;
for (auto it = m_mapPtrSize.cbegin(); it != m_mapPtrSize.cend(); it++)
{
sSize += it->second;
}
return sSize;
}
LPARAM getBuffer()
{
// Create a buffer big enough for all the fields
//
LPARAM pBuf = reinterpret_cast<LPARAM> (new (std::nothrow) BYTE[getSize()]);
if (pBuf == NULL)
return NULL;
DWORD offset = 0;
for (auto it = m_mapPtrSize.cbegin(); it != m_mapPtrSize.cend(); it++)
{
// Copy the fields one at a time, offsetting into the buffer
//
memcpy((void*) (pBuf + offset), (const void*) it->first, it->second);
offset += it->second;
}
return pBuf;
}
protected:
private:
std::vector<std::pair<const LPARAM, DWORD>> m_mapPtrSize;
};
這讓我爲我解析XML執行以下操作類型:
DynamicStructure dynStruct;
int a = 1;
float b = 2.3f;
double c = 3.5;
wchar_t * d = L"bob";
dynStruct.addField(a);
dynStruct.addField(b);
dynStruct.addField(c);
dynStruct.addField(d);
// Test - does the dymanic structure match the user's structure?
LPARAM pBuf = dynStruct.getBuffer();
test1 * pTest1 = (test1 *) pBuf;
std::wcout << pTest1->a << " " << pTest1->b << " " << pTest1->c << " " << pTest1->d << std::endl;
這並不完美,它有點老派,但至少它很簡單,並提供了一個合理的安全水平。
我不會認爲如果您知道它是參數,那麼需要全反射API來以朦朧的方式調用函數。畢竟,如果你知道調用約定(我這麼做),從理論上來說,在彙編器中做「足夠」就夠了。我只是想知道是否有一個好的方法來在標準C++中做到這一點。我想我可以使用一大堆void *風格的函數,並選擇我需要的那一個,然後他們必須將指針投回......但這似乎有點廢話。 – Benj 2012-01-12 11:47:46
@Benj不,你不需要全面反思。我可能誤解了這個問題。該標準沒有說明如何加載庫並使用它的符號(這取決於平臺)。因爲你需要投,因爲你只能訪問c函數 – 2012-01-12 12:08:45
@Benj你問的是超複雜的問題。我鏈接了可以幫助你構建一個良好的插件框架的文章。 – 2012-01-12 12:11:09