0

我的代码如下所示:

extern "C" __declspec(dllexport)  myInterface(int id, void** pFunction)
{
   ...
}

我需要使 void** pFunction 参数指向一个函数,以便调用者可以通过 pFunction 指针使用这个函数。这个函数是通过 DLL 调用的,我不想这样做,但由于很多原因我别无选择。我知道COM是为此而设计的,但我不能使用它,原因归结为管理。

在这一点上,我不知道该怎么做,我所做的一切都给我带来了演员问题。有谁知道我该怎么做?如果不清楚,我可以发布更多内容。

谢谢。

4

5 回答 5

3

如果您正在查看“myInterface”的实现,那么您可能想要:

switch (id)
{
case FUNC_1:
    *pFunction = (void *)first_function;
    break;
...
}

如果您尝试调用函数并传入指向函数的指针,则:

void *vp = (void *)the_function_to_pass;
myInterface(1, &vp);

如果您有其他想法,则需要指定什么。

(请注意,严格来说,C 不保证可以将函数指针分配给对象指针,反之亦然。但是,POSIX 确实为您做出了保证。我相信类似的评论也适用于 C++。)

于 2010-07-16T21:20:00.007 回答
1

这不是在标准 C 或 C++ 中可以完成的事情。无法保证函数指针可以放入 void 指针(C++ 成员函数指针通常不能)。换句话说,如果您不能更改函数签名,那么您就无法在标准 C 或 C++ 中做您想做的事情,也无法保证您完全可以做到。

因此,任何解决方案都将是特定于平台的解决方案。您没有直接在问题或标签中指定平台,但我的猜测是来自其他事物的 Visual C++。

请具体指定您的平台,以及有关您要传递的函数指针的任何有用信息。

于 2010-07-16T21:18:14.183 回答
1

这很棘手,但我对这样的代码很幸运:

*reinterpret_cast<void**>( &(PVOID&)( DetourFunc ) ) = (PVOID) 0x00FFFF00; 

据我了解,这个概念是你引用一个引用,重新解释引用,然后取消引用它。有点混乱,但我可以验证它是否有效。您也可以在右侧添加一个地址 (&func),这样就可以了。使用以下形式调用 DetourFunc:

(DetourFunc)(param, param)

将调用原始地址或函数。

编辑:这行得通,但它似乎是对语言的严重滥用。不过,它确实有效,并且已在此处的其他几个问题中被推荐。

于 2010-07-16T21:37:08.310 回答
1

正如 Jonathan Leffler 和 David Thornley 提到的,不能保证函数指针可以相互转换void*。一种可移植的解决方法是将函数指针打包到 astruct中并将指针传递给它。

(请注意,void**它本身可能有自己的问题。您也可以避免这种情况。)

例如:

typedef int (*SomeFuncType)(int);

struct FuncWrapper
{
    SomeFuncType func;
    void* output;
};

...
FuncWrapper funcWrapper;
funcWrapper.func = ...;

myInterface(id, &funcWrapper);

然后 myInterface 可以实现为:

void myInterface(int id, FuncWrapper* funcWrapper)
{
    funcWrapper->func(...);
    funcWrapper->output = ...;
}
于 2010-07-16T21:39:22.583 回答
0

我要感谢大家的帮助。这是我如何让它至少部分工作的方法。基本上包装的想法是有效的。

struct myProj { virtual HRESULT __stdcall myMethod(unsigned short* & myname); };

HRESULT __stdcall myMethod(unsigned short* & myname) { myname = L"myname";

返回(1);}

结构 myProj xProject;

调用它:

extern "C" HRESULT __declspec(dllexport) fInterface(UINT id, LPVOID * pObj) { switch(id) { case FVI_ID: *pObj = &xProject; 休息; } }

这确实调用了正确的函数,但它仍然存在问题。第三方 DLL 使用 CStrings,我怀疑它们会给我带来其他问题以及它们包含的一些跟踪函数。

我相信我真正的解决方案是我不能伪造 com,我们需要意识到 DLL 不能在我们的项目中使用。

谢谢大家。

于 2010-07-19T18:39:58.423 回答