如何使void **指向一个函数?

时间:2010-07-16 21:13:13

标签: c++ function-pointers void-pointers

我的代码如下:

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

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

此时我不知道该怎么做,我试图做的每件事都给我带来了问题。有谁知道我怎么能这样做?如果不清楚,我可以发布更多内容。

感谢。

5 个答案:

答案 0 :(得分: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 ++。)

答案 1 :(得分:1)

这不是可以在标准C或C ++中完成的事情。无法保证函数指针可以适合void指针(C ++成员函数指针通常不能)。换句话说,如果您无法更改功能签名,则无法在标准C或C ++中执行所需操作,并且无法保证您可以执行此操作。

因此,任何解决方案都是特定于平台的解决方案。您没有直接指定问题或标记的平台,但我的猜测是其他东西的Visual C ++。

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

答案 2 :(得分:1)

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

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

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

(DetourFunc)(param, param)

将调用原始地址或函数。

编辑:这样可行,但似乎是对语言的滥用。但它确实有效,并且在此处的其他几个问题中也有所建议。

答案 3 :(得分:1)

正如Jonathan Leffler和David Thornley所提到的,你无法保证函数指针可以转换为void*并返回。一个可移植的解决方法是将函数指针打包到struct并传递指针。

(请注意void** itself might have its own issues。您也可以避免这种情况。)

例如:

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 = ...;
}

答案 4 :(得分:0)

我要感谢大家的帮助。以下是我至少部分工作的方式。基本上包装理念是有效的。

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

HRESULT __stdcall myMethod(unsigned short *&amp; myname) {    myname = L“myname”;

返回(1); }

struct myProj xProject;

要打电话:

extern“C”HRESULT __declspec(dllexport)fInterface(UINT id,LPVOID * pObj) {    开关(ID)    {        案例FVI_ID:        * pObj =&amp; xProject;        打破;    } }

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

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

谢谢大家。