Как заставить void ** указывать на функцию? - PullRequest
0 голосов
/ 17 июля 2010

У меня есть код, который выглядит так:

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

Мне нужно, чтобы аргумент void ** pFunction указывал на функцию, чтобы вызывающая сторона могла использовать эту функцию через указатель pFunction. Эта функция вызывается через DLL, я не хочу делать это таким образом, но по многим причинам у меня нет выбора. Я знаю, что COM сделан для этого, но я не могу его использовать, причины сводятся к управлению.

На данный момент я понятия не имею, как это сделать, все, что я пытался сделать, вызывает у меня проблемы с актерами. У кого-нибудь есть идеи, как я могу это сделать? Я могу опубликовать больше, если это неясно.

Спасибо.

Ответы [ 5 ]

3 голосов
/ 17 июля 2010

Если вы смотрите на реализацию 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 голос
/ 17 июля 2010

Как упоминали Джонатан Леффлер и Дэвид Торнли, вам не гарантируется, что указатель функции можно преобразовать в void* и обратно. Переносимый обходной путь - упаковать указатель функции в struct и передать указатель на него.

(Имейте в виду, что 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 = ...;
}
1 голос
/ 17 июля 2010

Это сложно, но мне повезло с таким кодом:

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

Идея, насколько я понимаю, заключается в том, что вы ссылаетесь на ссылку, интерпретируете ссылку, а затем разыменовываете ее,Немного смущает, но я могу убедиться, что это работает.Вы также можете поместить адрес справа (& func), и он будет работать.Вызов DetourFunc с использованием формы:

(DetourFunc)(param, param)

вызовет исходный адрес или функцию.

Редактировать: Это работает, но выглядит как довольно серьезное злоупотреблениеязык.Это работает, однако, и было рекомендовано в нескольких других вопросах здесь.

1 голос
/ 17 июля 2010

Это не то, что можно сделать в стандарте C или C ++.Нет гарантии, что указатель на функцию может вписаться в указатель void (указатели на функции-члены C ++ обычно не могут).Другими словами, если вы не можете изменить сигнатуру функции, вы не можете делать то, что вы хотите в стандарте C или C ++, и нет никакой гарантии, что вы вообще сможете это сделать.

Поэтому любое решение можетбыть платформо-зависимым.Вы не указываете платформу непосредственно в вопросе или теге, но я полагаю, что Visual C ++ будет из других вещей.

Пожалуйста, укажите конкретно вашу платформу и что-нибудь полезное в указателе функции, который вы хотите передать.*

0 голосов
/ 19 июля 2010

Я хочу поблагодарить всех за помощь.Вот как я заставляю его работать хотя бы частично.В основном идея обертки работает.

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

HRESULT __stdcall myMethod (без знака short * & myname) {myname = L "myname";

return (1);}

struct myProj xProject;

Для его вызова:

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

Это вызывает правильную функцию, но у нее все еще есть проблемы.Сторонняя DLL использует CStrings, и я подозреваю, что они дают другие мои проблемы, а также некоторые функции трассировки, которые они содержат.

Я считаю, что мое реальное решение - я не могу подделать ком, что нам нужно понять,DLL не могут быть использованы в нашем проекте.

Спасибо всем.

...