Ошибка C2664 из-за конфликта cdecl и myclass

Я пытаюсь присоединить старый кусок кода на C к моему нынешнему проекту VC++:

// .h
    class DMSinv : public CDialog {
        double finte(double z);
        double ITFStolz(double Zp1, double Zp2, double Zc);
    };

// .cpp
    double Zcglob;
    double DMSinv::finte(double z) 
    {
       return TFStolz(z, Zcglob);
    }

    double DMSinv::ITFStolz(double Zp1, double Zp2, double Zc)
    {
        int ierr;
        Zcglob = Zc;

        return (coteglob(&DMSinv::finte, Zp1, Zp2, 1.0e-10, &ierr));
    //error C2664: 'DMSinv::coteglob' : cannot convert parameter 1 from 'double (__thiscall DMSinv::* )(double)' to 'double (__cdecl *)(double)'    

    }

функция coteglob происходит из старой части C, а finte является промежуточной функцией для передачи функции TFStolz в coteglob.

Я искал в форумах и нашел этот связанный вопрос: Как преобразовать указатель void (__thiscall MyClass::*)(void *) в void (__cdecl *)(void *), который я пытался применить таким образом:

// .h
    class DMSinv : public CDialog {
        virtual double finte(double z);
        double ITFStolz(double Zp1, double Zp2, double Zc);
    };

// .cpp
    double Zcglob;
    extern "C"
    {
        static double __cdecl finteHelper(double z)
        {
            DMSinv* datainv = reinterpret_cast< DMSinv > (z); //error C2440: 'reinterpret_cast' : cannot convert from 'double' to 'DMSinv'  

            datainv->finte(z);
        }
    }

    double DMSinv::ITFStolz(double Zp1, double Zp2, double Zc)
    {
        int ierr;
        Zcglob = Zc;
        double solution = coteglob(&finteHelper, Zp1, Zp2, 1.0e-10, &ierr);
        return solution;
    }

но все еще не работает. Кто-нибудь может подсказать мне, как его адаптировать? Я еще новичок, и это, кажется, далеко от моих знаний.

Заранее спасибо!

2 ответа

Решение

Не уверен, что это можно сделать, как вы хотите. Единственный вариант, который мне приходит в голову, - это использовать некоторую статическую переменную для хранения адреса объекта DMSinv. Это ограничивает вас до 1 потока с простой реализацией...

Попробуй это:

// .h
class DMSinv : public CDialog {
    double finte(double z);
    double ITFStolz(double Zp1, double Zp2, double Zc);

private:
  static DMSinv* _current;
  static double __cdecl finteHelper(double z);
};

// .cpp
double Zcglob;
DMSinv* DMSinv::_current = 0;
double DMSinv::finte(double z) 
{
   return TFStolz(z, Zcglob);
}

double DMSinv::ITFStolz(double Zp1, double Zp2, double Zc)
{
    int ierr;
    Zcglob = Zc;

   _current = this;
   return (coteglob(DMSinv::finteHelper, Zp1, Zp2, 1.0e-10, &ierr));
}

double __cdecl DMSinv::finteHelper(double z)
{
    return _current->finte(z);
}

Это не хорошее решение IMO, но я не уверен, что есть другой путь.

PS Чтобы снять ограничение одного потока, вы можете использовать слоты TLS или в VC++ просто __declspec(поток). С последним просто добавь __declspec(thread) в _current как это: static __declspec(thread) DMSinv* _current;, НО!!! знать, что число переменных для каждого потока ограничено для процесса. Подробнее об этом читайте в MSDN.

ОБНОВИТЬ

Disclamer: просто для удовольствия.

Теоретически, есть другая возможность. Вы можете хранить ассемблерный код в массиве, прикрепленном к объекту. Этот код сборки должен быть функцией __cdecl, которая просто переводит __cdecl в __thiscall на основе регистра eip. Но это никогда не должно быть сделано, хотя...:D

Я не думаю, что вы можете сделать это таким образом. Вам нужно как-то передать ссылку на ваш объект (this). В связанном вопросе параметр функции был определен как тип void * таким образом, вы можете передать все, что вам нужно, в функцию, включая указатель на this, Ваша функция принимает doubleтак что ты не можешь пройти this к этому.

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

double finte(double z) 
{
   return TFStolz(z, Zcglob);
}

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

Другие вопросы по тегам