如何让 void** 指向函数?

发布于 2024-09-10 02:53:39 字数 336 浏览 12 评论 0原文

我的代码如下所示:

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

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

此时我不知道该怎么做,我尝试做的一切都给我带来了演员问题。有谁知道我该怎么做?如果不清楚的话我可以发布更多内容。

谢谢。

I have code that looks like this:

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

I need to make the void** pFunction argument point to a function so that the caller can use this function via the pFunction pointer. This function gets called through a DLL, I don't want to do it this way but for a lot of reasons I have no choice. I know that COM is made for this but I can not use it, the reasons come down to management.

At this point I have no idea how to do this, everything I have tried to do gives me cast problems. Do anyone have any idea how I can do this? I can post more if this is unclear.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

逆流 2024-09-17 02:53:39

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

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

如果您尝试调用该函数并传入函数指针,那么:

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

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

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

If you are looking at the implementation of 'myInterface', then you might be wanting:

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

If you are trying to call the function and pass in a pointer to function, then:

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

If you have something else in mind, you need to specify what.

(Note that strictly, C does not guarantee that function pointers can be assigned to object pointers and vice versa. However, POSIX does make that guarantee for you. I believe similar comments apply to C++.)

一杆小烟枪 2024-09-17 02:53:39

正如 Jonathan Leffler 和 David Thornley 提到的,不能保证函数指针可以转换为 void* 并返回。一个可移植的解决方法是将函数指针打包到一个结构体中,并传递一个指向该结构体的指针。

(请注意,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 = ...;
}

As Jonathan Leffler and David Thornley mentioned, you aren't guaranteed that a function pointer can be converted to void* and back. A portable workaround would be to package the function pointer into a struct and to pass a pointer to that.

(Be aware that void** itself might have its own issues. You can avoid this too.)

For example:

typedef int (*SomeFuncType)(int);

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

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

myInterface(id, &funcWrapper);

and then myInterface could be implemented as:

void myInterface(int id, FuncWrapper* funcWrapper)
{
    funcWrapper->func(...);
    funcWrapper->output = ...;
}
笑脸一如从前 2024-09-17 02:53:39

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

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

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

This is not something that can be done in standard C or C++. There is no guarantee that a function pointer can fit into a void pointer (C++ member function pointers typically can't). In other words, if you can't change the function signature, you can't do what you want in standard C or C++, and there's no guarantee you can do it at all.

Therefore, any solution would be a platform-specific one. You don't specify a platform directly in question or tag, but my guess would be Visual C++ from other things.

Please specify your platform specifically, and anything useful about the function pointer you want to pass.

凯凯我们等你回来 2024-09-17 02:53:39

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

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

据我了解,这个概念是您引用一个引用,重新解释该引用,然后取消引用它。有点令人困惑,但我可以验证它是否有效。您还可以在右侧放置一个地址(&func),它就会起作用。调用DetourFunc,使用形式:

(DetourFunc)(param, param)

将调用原始地址或函数。

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

It's tricksy, but I've had good luck with code like so:

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

The concept, as I understand it, is you're referencing a reference, reinterpreting the reference, then dereferencing it. Bit confusing, but I can verify it works. You can also put an address on the right side (&func) and it'll work. Calling DetourFunc, using the form:

(DetourFunc)(param, param)

will call the original address or function.

Edit: This works, but it seems like a pretty heavy abuse of the language. It does work, though, and has been recommended in a few other questions here.

慢慢从新开始 2024-09-17 02:53:39

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

结构myProj
{
虚拟 HRESULT __stdcall myMethod(unsigned Short* & myname);
};

HRESULT __stdcall myMethod(无符号短* & myname)
{
我的名字 = L"我的名字";

返回(1);
}

结构 myProj xProject;

调用它:

extern "C" HRESULT __declspec(dllexport) fInterface(UINT id, LPVOID * pObj)
{
开关(ID)
{
案例 FVI_ID:
*pObj = &xProject;
休息;
}

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

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

谢谢大家。

I want to thank everyone for help. Here is how I get it to work at least in part. Basically the wrapper idea works.

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

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

return(1);
}

struct myProj xProject;

To call it:

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

This does call the correct function, but it still has it's problems. The third party DLL uses CStrings and I suspect they are giving my other problems as well as some trace functions they contain.

I believe my real solution is I can't fake out the com, that we need to realize the DLL's can not be used in our project.

Thanks everyone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文