Re[2]: Указатель на функцию
От: Андрей Тарасевич Беларусь  
Дата: 22.12.04 09:03
Оценка:
Здравствуйте, А.Якубовский, Вы писали:

АЯ>
АЯ>B b;
АЯ>Method m(&b,B::F1);
АЯ>


Во-первых, язык С++ не позволяет получть указатель на метод класса без явного использования оператора '&'. Поэтому правильно так

Method m(&b, &B::F1);


(это для любителей изучать язык по ошибкам (и глюкам) компиляторов).

Во-вторых, чтение аргумента типа "указатель на метод класса" через 'va_arg(..., void*)' является банальным хаком, ибо приводит к неопределенному поведению (это к вопросу о приведении типов "без хака").

Во-третих, давай, продемонстрируй нам, как же ты собрался вызывать методы классов через твой "указатель" Я думаю тут никому не составить труда привести тебе хрестоматийный уже пример из пяти-десяти строк, на котором твой "указатель" быстро и громко сядет в лужу
Best regards,
Андрей Тарасевич
Re[2]: Указатель на функцию
От: Dark Angel Украина  
Дата: 22.12.04 09:06
Оценка: 1 (1) +1
Hello, А.Якубовский!
You wrote on Wed, 22 Dec 2004 08:41:16 GMT:

А>

[Sorry, skipped] 

 А> теперь внимание ответ. 
 А> [code]
 А> struct Method {
 А>  void*  mthdOwner;
 А>  void* mthdFunction;
 А>  Method(void* Owner,...)
 А>  {
 А>   va_list mthd;
 А>   va_start(mthd,Owner);
 А>   mthdOwner = Owner;
 А>   mthdFunction = va_arg(mthd,void*);
 А>   va_end(mthd);
 А>  }
 А> };

 А> Ну и где то в коде 

 А> B b;
 А> Method m(&b,B::F1);

 А>


А> И теперь пусть хоть кто-то скажет что нельзя привести указатель на

А> функцию к типу войд*, или другому типу

Я вам скажу, что Вы облажались Я тоже могу написать
 void* tmp = reinterpret_cast<void*>(&A::F1);
, но знаете, как бы я не изгалялся это будет undefined behaviour. То же самое вы и имеете в Вашем случае — вам удалось заставить это работать в частном случае. Надеюсь Вадим Никулин развеял ваши заблуждения.

With best regards, Konstantin Litvinenko.
Posted via RSDN NNTP Server 1.8
Re[4]: Указатель на функцию
От: Кодт Россия  
Дата: 22.12.04 09:08
Оценка: :))
Здравствуйте, А.Якубовский, Вы писали:

АЯ>Во первых никогда не встречал чтоб указатель на 32-битной платформе был больше 32

АЯ>А вам блин еще и подай как маршалинг у меня реализован на основе этого кода. Я блин парился всю ночь, по дружные издевки, а потом дайте мне плз. реализацию маршалинга. Ребята не по взрослому получается.

И не говори! Совсем не по-взрослому. Это даже не детский сад. И даже не yasli
Ну ничего. Даже после 14 лет практики можно узнать много нового

Кстати. 14 лет назад ты для какой платформы писал? Win16, DOS, MacOS, VAX? Удивительно, что ты не столкнулся с тем фактом, что нельзя приводить указатели на данные и на функции.

PS.
Обычно код, над которым пишут в угаре, — работает только с бодуна.
Перекуём баги на фичи!
Re[4]: Указатель на функцию
От: Андрей Тарасевич Беларусь  
Дата: 22.12.04 09:08
Оценка:
Здравствуйте, А.Якубовский, Вы писали:

G>>Ээээ..

G>>1) А как теперь пользотвать этот класс мэтода?
G>>2) Что случится если sizeof(void*) < sizeof(void A::*) ?

АЯ>Во первых никогда не встречал чтоб указатель на 32-битной платформе был больше 32


Век живи — век учись. На 32-хбитной платформе битовый размер легального указателя на метод класса всегда строго больше 32-х бит. Например, на платформе MSVC++ указатель на метод класса, корректно работающий в условиях множественного наследования имеет размер 64 бита. Это и есть та причина, по котрой вопросы приведения указателя на метод класса к типу 'void*' не заслуживают никакого серъезного рассмотрения.
Best regards,
Андрей Тарасевич
Re[3]: Указатель на функцию
От: А.Якубовский  
Дата: 22.12.04 09:09
Оценка:
Здравствуйте, Кодт, Вы писали:

Не ну вы че издеваетесь. Мне пофиг вопрос был задекларирован. Я дал Вам на него ответ, Функции у меня вызываются на ура, и с виртуальным наследованием и без. Как у вас будут вызываться я не знаю это не мое дело. Читайте тему топика. Можно ли привети указатель на функцию к типу войд*, я не собирался распространяться на тему как использовать это дальше.
Re[4]: Указатель на функцию
От: Glоbus Украина  
Дата: 22.12.04 09:12
Оценка:
Здравствуйте, А.Якубовский, Вы писали:

АЯ>Здравствуйте, Glоbus, Вы писали:


G>>Здравствуйте, А.Якубовский, Вы писали:


G>>Ээээ..

G>>1) А как теперь пользотвать этот класс мэтода?
G>>2) Что случится если sizeof(void*) < sizeof(void A::*) ?

АЯ>Во первых никогда не встречал чтоб указатель на 32-битной платформе был больше 32


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

АЯ>А вам блин еще и подай как маршалинг у меня реализован на основе этого кода. Я блин парился всю ночь, по дружные издевки, а потом дайте мне плз. реализацию маршалинга. Ребята не по взрослому получается.


А мы тут все скопом жестко щас наживетмся на тебе и твоем маршалинге

Ближе к делу. Если уж ты так реально парился, здается мне что парился ты зря, хотя бы потому, что можно одним движением руки избавиться от вопроса sizeof(void*) < sizeof(void A::*)

struct Method {
 void*    mthdOwner;
 void (A::*mthdFunction)();
 Method(void* Owner,...)
 {
  va_list mthd;
  va_start(mthd,Owner);
  mthdOwner    = Owner;
  mthdFunction    = va_arg(mthd,void A::*);
  va_end(mthd);
 }
};
Удачи тебе, браток!
Re[3]: Указатель на функцию
От: Андрей Тарасевич Беларусь  
Дата: 22.12.04 09:13
Оценка:
Здравствуйте, eao197, Вы писали:


E>Результат работы под VC++ 7.1:

E>sizeof(vp): 4, sizeof(mp): 4

Такой результат ты получишь только при "агрессивных" установках компиляции, при которых указатели на методы классов в MSVC++ в общем случае работают некорректно. При включении "нормальных" установок компиляции размер указателя на метод класса становится равным 16. Есть "промежуточная" установка, при котором размер будет равен 8.
Best regards,
Андрей Тарасевич
Re[4]: Указатель на функцию
От: Вадим Никулин Россия Здесь
Дата: 22.12.04 09:13
Оценка:
Здравствуйте, А.Якубовский, Вы писали:

АЯ>Здравствуйте, Кодт, Вы писали:


АЯ>Не ну вы че издеваетесь. Мне пофиг вопрос был задекларирован. Я дал Вам на него ответ, Функции у меня вызываются на ура, и с виртуальным наследованием и без. Как у вас будут вызываться я не знаю это не мое дело. Читайте тему топика. Можно ли привети указатель на функцию к типу войд*, я не собирался распространяться на тему как использовать это дальше.


Ты че, друг! Хочешь, чтобы IT-индустрия простаивала из-за тебя целый день, пытаясь доказать, что твое решение не работает? Ты пробовал вызывать ЭТО для классов с виртуальным наследованием?
Читай еще раз здесь
Автор: Кодт
Дата: 22.12.04
Re[4]: Указатель на функцию
От: Аноним  
Дата: 22.12.04 09:13
Оценка:
Здравствуйте, А.Якубовский, Вы писали:

АЯ>Здравствуйте, Кодт, Вы писали:


АЯ>Не ну вы че издеваетесь.


Какие издевки.
Не дай бог юзать софт, или еще хуже сопровождать такой
код, где что-то иногда, в очень частных случаях работает.

Я за свои 7 лет опыта (меньше твоего) уже устал
бороться с такими и подобными хаками, хуками и прочими подобными прелестями.
Зачем делать через задницу, когда есть нормальные надежные решения.
Но это уже полный уход от темы.
Re[4]: Указатель на функцию
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.12.04 09:16
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Здравствуйте, eao197, Вы писали:



E>>Результат работы под VC++ 7.1:

E>>sizeof(vp): 4, sizeof(mp): 4

АТ>Такой результат ты получишь только при "агрессивных" установках компиляции, при которых указатели на методы классов в MSVC++ в общем случае работают некорректно. При включении "нормальных" установок компиляции размер указателя на метод класса становится равным 16. Есть "промежуточная" установка, при котором размер будет равен 8.


Запускал компиляцию так:
cl -GX meth_ptr_size.cpp

Потом просто запустил meth_ptr_size.exe


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: Указатель на функцию
От: Андрей Тарасевич Беларусь  
Дата: 22.12.04 09:17
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Боюсь, что мы сейчас увидим решение с ..., thunks в стиле ATL или еще что-нть непереносимое.


Решение, как видишь, уже опубликовано и включает банальное силовое (и, разумеется, некорректное) приведение указателя на метод к типу 'void*'. Гора родила мышь. Как и следовало ожидать, автор решения наивно полагает, что указатель на метод класса состоит только из адреса точки входа в метод
Best regards,
Андрей Тарасевич
Re: Указатель на функцию
От: А.Якубовский  
Дата: 22.12.04 09:21
Оценка: -3 :))) :))) :)
Здравствуйте, Irokez, Вы писали:

censored. П. 5 обязательных правил форумов РСДН.

То г-н Тарасевич, крутой спец по с++, теорик. Никогда не "бравший" в руки отладчик типа Soft Ice или хотя-бы встроенный. Вам как особо одаренному поясню После линковки, в теле программы идет вызов следующего типа. Извините что испоганю асмом ваш любимы С++, но все же

mov ecx, this — я пишу в некотором отступлении от стандартного асма, но что одаренным C++ программистам было понятно
mov eax, dword ptr [ecx+4] — это к примеру вызов виртуального метода +4 это адресс виртуальной функции в таблице vtbl
...

push param1
push param2
push param3
push ecx неявная передача this через стек
call eax

....

Так вот если-б вы зоть раз соизволили сделать трасировку в асме, ВЫ бы подумали прежде чем написать что указатель может быть больше 32

Re[5]: Указатель на функцию
От: Кодт Россия  
Дата: 22.12.04 09:26
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Век живи — век учись. На 32-хбитной платформе битовый размер легального указателя на метод класса всегда строго больше 32-х бит. Например, на платформе MSVC++ указатель на метод класса, корректно работающий в условиях множественного наследования имеет размер 64 бита. Это и есть та причина, по котрой вопросы приведения указателя на метод класса к типу 'void*' не заслуживают никакого серъезного рассмотрения.


Во! Точно! Я не мог вспомнить, в каких случаях получается 128-битный указатель... Виртуальное наследование + множественное наследование + виртуальные функции. Вуаля!
Перекуём баги на фичи!
Re[4]: Указатель на функцию
От: Glоbus Украина  
Дата: 22.12.04 09:26
Оценка: 1 (1)
Здравствуйте, А.Якубовский, Вы писали:

АЯ>Здравствуйте, Кодт, Вы писали:


АЯ>Не ну вы че издеваетесь. Мне пофиг вопрос был задекларирован. Я дал Вам на него ответ, Функции у меня вызываются на ура, и с виртуальным наследованием и без. Как у вас будут вызываться я не знаю это не мое дело. Читайте тему топика. Можно ли привети указатель на функцию к типу войд*, я не собирался распространяться на тему как использовать это дальше.


Держите меня трое И у этого человека 14 лет опыта в Си и Си++
Старик, то что ты сделал это не привдение типа — это не приведение типа. Просто потому что нельзя привести тип void* к типу указателя на функцию. А то что там у тебя — это просто запись в стек sizeof(void B::*) байт и выгребалово sizeof(void*) байтю А куда же остальные sizeof(void B::*) — sizeof(void*) байт деть?
Удачи тебе, браток!
Re[4]: Указатель на функцию
От: Кодт Россия  
Дата: 22.12.04 09:29
Оценка:
Здравствуйте, А.Якубовский, Вы писали:

АЯ>Не ну вы че издеваетесь. Мне пофиг вопрос был задекларирован. Я дал Вам на него ответ, Функции у меня вызываются на ура, и с виртуальным наследованием и без. Как у вас будут вызываться я не знаю это не мое дело. Читайте тему топика. Можно ли привети указатель на функцию к типу войд*, я не собирался распространяться на тему как использовать это дальше.


Ну ради бога. У тебя компилируется и работает. Только я твои программы на свой компьютер не пущу.

"Неправильный ответ — тоже ответ" (по аналогии с отрицательным результатом).
Перекуём баги на фичи!
Re: Указатель на функцию
От: А.Якубовский  
Дата: 22.12.04 09:33
Оценка:
Здравствуйте, Irokez, Вы писали:

class A {
public:
void __stdcall Fn1()
{
printf("A::Fn1()\n");
}
virtual void __stdcall Fn2() = 0;
};

class B : public virtual A{
public:
void __stdcall Fn1(int& k,int& d)
{
printf("B::Fn1(%d-%d)\n",k,d);
}
virtual void __stdcall Fn2()
{
printf("B::Fn2()\n");
}
};


у меня наследование такое. И все чудно работает
Re[4]: Указатель на функцию
От: Dark Angel Украина  
Дата: 22.12.04 09:38
Оценка:
Hello, А.Якубовский!
You wrote on Wed, 22 Dec 2004 09:09:03 GMT:

А> Не ну вы че издеваетесь. Мне пофиг вопрос был задекларирован. Я дал Вам

А> на него ответ, Функции у меня вызываются на ура, и с виртуальным
А> наследованием и без. Как у вас будут вызываться я не знаю это не мое
А> дело. Читайте тему топика. Можно ли привети указатель на функцию к
А> типу войд*
, я не собирался распространяться на тему как использовать
А> это дальше.

Мне кажеться Вы непоняли — в С++ приводить типы можна какие угодно к каким угодно. Но от этого программа не остается правильной, а неправильные программы могут представлять только академический интерес, уж ни как не промышленный. А зачем нам кони в вакууме? Правильно, незачем. А доказательство в стиле "это у меня работает" никогда не было таковым.

With best regards, Konstantin Litvinenko.
Posted via RSDN NNTP Server 1.8
Re[2]: Указатель на функцию
От: Андрей Тарасевич Беларусь  
Дата: 22.12.04 09:47
Оценка:
Здравствуйте, А.Якубовский, Вы писали:

АЯ>mov ecx, this — я пишу в некотором отступлении от стандартного асма, но что одаренным C++ программистам было понятно

АЯ>mov eax, dword ptr [ecx+4] — это к примеру вызов виртуального метода +4 это адресс виртуальной функции в таблице vtbl
АЯ>...

АЯ>push param1

АЯ>push param2
АЯ>push param3
АЯ>push ecx неявная передача this через стек
АЯ>call eax

АЯ>....


АЯ>Так вот если-б вы зоть раз соизволили сделать трасировку в асме, ВЫ бы подумали прежде чем написать что указатель может быть больше 32


Душит смех. Нет, молодой человек, если бы Вы хоть раз сделали трассировку правильно откомпилированной программы "в АСМЕ" и поcмотрели, как выглядит вызов метода класса через корректно сформированный указатель на метод класса, Вы бы никогда не стали писать здесь всю эту белиберду и публично садиться в лужу еще и с "асмом".

Специально для Вас я приведу здесь очень показательный пример этого самого "асма" для вызова метода класа через указатель.

Вот С++ код

#include <iostream>

struct A {
  int i;
  A() : i(1) {}
  void print() { std::cout << i << std::endl; }
};

struct B {
  int i;
  B() : i(2) {}
  void print() { std::cout << i << std::endl; }
};

struct C : A, B {
  int i;
  C() : i(3) {}
};

void call(C* pc, void (C::*pm)()) {
  (pc->*pm)();
}

int main() {
  C c;
  call(&c, &A::print);
  call(&c, &B::print);
}


А вот Вам ассмеблерный код функции 'call'

00401080   mov         eax,dword ptr [esp+4]
00401084   mov         ecx,dword ptr [esp+0Ch]
00401088   add         ecx,eax
0040108A   jmp         dword ptr [esp+8]


Поясню: обе выделенные жирным инструкции занимаются чтением частей указателя 'pm', который располагается в стеке по адресам esp+4 и esp+8. Советую вам тщательно разобрать этот код и хорошенько подумать о том, что же делают эти две инструкции и почему же это они читают из 32-хбитного (как Вы полагаете) указателя 64 бита информации.
Best regards,
Андрей Тарасевич
Re[2]: Указатель на функцию
От: Кодт Россия  
Дата: 22.12.04 09:52
Оценка: +2 :))
Здравствуйте, А.Якубовский, Вы писали:

АЯ>у меня наследование такое. И все чудно работает


Покажи полный код рабочего примера. Без урывочков...

Кстати, специально для любителей отладки. Вот, соорудил из твоих кусочков:
#include <stdio.h>
#include <stdarg.h>

class A
{
public:
    void __stdcall Fn1()
    {
        printf("A::Fn1()\n");
    }
    virtual void __stdcall Fn2() = 0;
};

class B : public virtual A
{
public:
    void __stdcall Fn1(int& k,int& d)
    {
        printf("B::Fn1(%d-%d)\n",k,d);
    }
    virtual void __stdcall Fn2()
    {
        printf("B::Fn2()\n");
    }
};

struct Method
{
    Method(void* Owner,...)
    {
        va_list mthd;
        va_start(mthd,Owner);
        mthdOwner = Owner;
        unsigned long tag1 = va_arg(mthd,unsigned long);
        mthdFunction  = va_arg(mthd,void*);
        unsigned long tag2 = va_arg(mthd,unsigned long);
        printf("owner = %p, tag1 = %08X, func = %p, tag2 = %08X\n", mthdOwner, tag1, mthdFunction, tag2);
        va_end(mthd);
        // dump the stack again...
        printf("Ellipsis is ...\n");
        va_start(mthd,Owner);
        do
        {
            tag2 = va_arg(mthd,unsigned long);
            printf("... %08X\n", tag2);
        }
        while(tag2 != 0xDEADBEEF);
        va_end(mthd);
    }
};

int main()
{
    B b;
    Method m(&b, 0xFEEDFACE, &B::Fn2, 0xDEADBEEF);
}

Вывод:
owner = 0012FF78, tag1 = FEEDFACE, func = 004011A0, tag2 = 00000000 <--- а где же дохлая корова?
Ellipsis is ...
... FEEDFACE
... 004011A0
... 00000000
... 00000004
... DEADBEEF         <--- а вот она!
Перекуём баги на фичи!
Re[3]: Указатель на функцию
От: Аноним  
Дата: 22.12.04 10:01
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

Ну извините всех кого я обидел. Я так понимаю модератор меня забанил. Но еще раз повторюсь без эмоций, вопрос стоял так
Можно ли привети указатель к типу войд*. Я специально поставил вопрос таким образом, чтобы можно было понять впринципе возможно ли приведение типов функций. Я для себя ответ нашед можно. Здесь я опубликовал именно ответ на свой вопрос о приведении к типу войд*.

Теперь дабы достичь консенсуа а приведу код который действительно у меня написан.

Обратите пожалуйста внимание на __stdcall. Я готов пообсуждать без эмоций в чем я не прав. Токо пжалуйста не надо стучать себя кулоком в грудь и говорить что тут полный бред.
struct Method {
    typedef long (__stdcall Method::*Function)();
    void*        mthdOwner;
    Function    mthdFunction;
    Method(void* Owner,...)
    {
        va_list mthd;
        va_start(mthd,Owner);
        mthdOwner        = Owner;
        mthdFunction    = static_cast<Function>(va_arg(mthd,Function));
        va_end(mthd);
    }
    long Run(int iCount,...)
    {
        void* pArgs[10];

        void* Owner = mthdOwner;
        void* Fn = mthdFunction;
        long Result;

        va_list marker;
        va_start( marker, iCount );

        int i=0;
        while(iCount --){
            pArgs[i ++] = va_arg( marker, void*);
        }
        va_end(marker);

        while(i--){
            __asm mov eax,i
            __asm mov eax,dword ptr pArgs[eax*4]
            __asm push eax

        }

        __asm push Owner
        __asm mov eax,Fn
        __asm call eax

        return Result;
    }
};
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.