我决定做的就是使插件接受一个简单的接口:
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