Ошибка функции C ++ Builder [bcc32 - ошибка неоднозначности] внутри файла dll - PullRequest
0 голосов
/ 02 мая 2018

Я создаю программу конвертации валют Win32 в Embarcadero C ++ Builder. Я написал функцию для преобразования даты из формата, указанного на компьютере пользователя, в формат YYYY-MM-DD. Мне нужна эта часть из-за настроек API.

Когда у меня есть эта функция внутри моего проекта, она работает нормально, но мне нужно, чтобы эта функция была внутри DLL.

Вот так выглядит мой код:

#pragma hdrstop
#pragma argsused
#include <SysUtils.hpp>

extern DELPHI_PACKAGE void __fastcall DecodeDate(const System::TDateTime DateTime, System::Word &Year, System::Word &Month, System::Word &Day);

extern "C" UnicodeString __declspec (dllexport) __stdcall datum(TDateTime dat) {
    Word dan, mjesec, godina;
    UnicodeString datum, datum_dan, datum_mjesec, datum_godina;
    DecodeDate(dat, godina, mjesec, dan);

    if (dan<=9 && mjesec<=9) {
        datum_dan="0"+IntToStr(dan);
        datum_mjesec="0"+IntToStr(mjesec);
    }

    if (dan<=9 && mjesec>9) {
        datum_dan="0"+IntToStr(dan);
        datum_mjesec=IntToStr(mjesec);
    }

    if (dan>9 && mjesec<=9) {
        datum_dan=IntToStr(dan);
        datum_mjesec="0"+IntToStr(mjesec);
    }

    if (dan>9 && mjesec>9) {
        datum_dan=IntToStr(dan);
        datum_mjesec=IntToStr(mjesec);
    }

    datum_godina=IntToStr(godina);

    return datum_godina+"-"+datum_mjesec+"-"+datum_dan;

}

extern "C" int _libmain(unsigned long reason)
{
    return 1;
}
    `

Я включил SysUtils.hpp и объявил функцию DecodeDate(), без этих строк у меня миллион ошибок. Но с кодом, похожим на этот, я получаю эту ошибку, от которой я не могу избавиться:

[bcc32 Error] File1.cpp(30): E2015 Ambiguity between '_fastcall System::Sysutils::DecodeDate(const System::TDateTime,unsigned short &,unsigned short &,unsigned short &) at c:\program files (x86)\embarcadero\studio\19.0\include\windows\rtl\System.SysUtils.hpp:3466' and '_fastcall DecodeDate(const System::TDateTime,unsigned short &,unsigned short &,unsigned short &) at File1.cpp:25'
  Full parser context
    File1.cpp(27): parsing: System::UnicodeString __stdcall datum(System::TDateTime)

Можете ли вы помочь мне избавиться от этой ошибки?

1 Ответ

0 голосов
/ 02 мая 2018

Сообщение об ошибке не требует пояснений. У вас есть две функции с одинаковым именем в области видимости, и компилятор не знает, какую из них вы хотите использовать в строке 30, поскольку передаваемые параметры удовлетворяют обоим объявлениям функций.

Чтобы исправить ошибку, вы можете изменить эту строку:

DecodeDate(dat, godina, mjesec, dan);

Для этого:

System::Sysutils::DecodeDate(dat, godina, mjesec, dan);

Или это:

dat.DecodeDate(&godina, &mjesec, &dan);

Однако, в любом случае, вам следует избавиться от объявления extern для DecodeDate(), так как оно вообще не входит в этот код. Вы не внедряете DecodeDate() самостоятельно, вы просто используете тот, который предоставлен RTL. Уже есть объявление для DecodeDate() в SysUtils.hpp, которое вы #include вводите в своем коде. Это все, что нужно компилятору.

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

Кстати, существует НАМНОГО более простой способ реализации логики вашей функции - вместо того, чтобы вручную отделять TDateTime и восстанавливать его компоненты, просто используйте функцию SysUtils::FormatDateTime() или TDateTime::FormatString() метод вместо, например:

UnicodeString __stdcall datum(TDateTime dat)
{
    return FormatDateTime(_D("yyyy'-'mm'-'dd"), dat);
}

UnicodeString __stdcall datum(TDateTime dat)
{
    return dat.FormatString(_D("yyyy'-'mm'-'dd"));
}

Тем не менее, этот код по-прежнему ошибочен, потому что небезопасно передавать не POD-типы, такие как UnicodeString, через границу DLL, как вы делаете. Вам нужно переосмыслить дизайн своей функции DLL, чтобы использовать только безопасные для взаимодействия типы POD. В этом случае измените свою функцию на:

  • принять wchar_t* в качестве ввода от звонящего и просто заполнить блок памяти нужными символами. Позвольте вызывающей стороне выделить фактический буфер и передать его в вашу DLL для заполнения:

    #pragma hdrstop
    #pragma argsused
    #include <SysUtils.hpp>
    
    extern "C" __declspec(dllexport) int __stdcall datum(double dat, wchar_t *buffer, int buflen)
    {
        UnicodeString s = FormatDateTime(_D("yyyy'-'mm'-'dd"), dat);
        if (!buffer) return s.Length() + 1;
        StrLCopy(buffer, s.c_str(), buflen-1);
        return StrLen(buffer);
    }
    
    extern "C" int _libmain(unsigned long reason)
    {
        return 1;
    }
    

    wchar_t buffer[12] = {};
    datum(SomeDateValueHere, buffer, 12);
    // use buffer as needed...
    

    int len = datum(SomeDateValueHere, NULL, 0);
    wchar_t *buffer = new wchar_t[len];
    int len = datum(SomeDateValueHere, buffer, len);
    // use buffer as needed...
    delete[] buffer;
    
  • выделяет буфер wchar_t[] для хранения нужных символов, а затем возвращает указатель wchar_t* на этот буфер вызывающей стороне. Затем экспортируйте вторую функцию, чтобы вызывающий мог передать вам возвращенный wchar_t*, чтобы вы могли его правильно освободить.

    #pragma hdrstop
    #pragma argsused
    #include <SysUtils.hpp>
    
    extern "C" __declspec(dllexport) wchar_t* __stdcall datum(double dat)
    {
        UnicodeString s = FormatDateTime("yyyy'-'mm'-'dd", dat);
        wchar_t* buffer = new wchar_t[s.Length()+1];
        StrLCopy(buffer, s.c_str(), s.Length());
        return buffer;
    }
    
    extern "C" __declspec(dllexport) void __stdcall free_datum(wchar_t *dat)
    {
        delete[] dat;
    }
    
    extern "C" int _libmain(unsigned long reason)
    {
        return 1;
    }
    

    wchar_t *buffer = datum(SomeDateValueHere);
    // use buffer as needed...
    free_datum(buffer);
    
...