Ошибка unresolved external builder c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "Main.h"
#include "SendMessage.h"
#include "ShowMessage.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "trayicon"
#pragma resource "*.dfm"
TMainForm *MainForm;
static AnsiString ComputerName;
static AnsiString Address;
static TListItem *LI;
static TStringList *UserList;
static AnsiString ADirectory;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::UDPServerUDPRead(TObject *Sender,TStream *AData, TIdSocketHandle *ABinding) {
     int Show;
     AnsiString Tmp,RemoteName,Message;
     TStringStream* SS=new TStringStream("");
     SS->CopyFrom(AData,AData->Size);
     Tmp=SS->DataString;
     RemoteName=Tmp.SubString(Tmp.Pos("(")+1,Tmp.Pos(")")-Tmp.Pos("(")-1);
     Show=1;
     if (Tmp.Pos("###Start###")!=0) {
        if (Tmp.Pos(ComputerName)==0) {
           if (MainForm->Active==True) {
              UDPServer->Send(ABinding->PeerIP,4000,"###Here And Active###("+ComputerName+")");
           } else {
              UDPServer->Send(ABinding->PeerIP,4000,"###Here And Inactive###("+ComputerName+")");
           }
           ChatInputOutput->Lines->Add("Подключился: "+RemoteName);
           UserList->Add(RemoteName);
           LI=UsersListView->Items->Add();
           LI->Caption=RemoteName;
           LI->ImageIndex=-1;
           LI->Indent=-1;
           LI->SubItems->Add("");
           LI->SubItemImages[0]=0;
           LI->SubItems->Add(""Неактивен"");
           MediaPlayer->FileName=ADirectory+"Start.wav";
           MediaPlayer->Open();
           MediaPlayer->Play();
        }
        Show=0;
     }
     if (Tmp.Pos("###Here And Active###")!=0) {
        if (Tmp.Pos(ComputerName)==0) {
           ChatInputOutput->Lines->Add("Уже в сети: "+RemoteName);
           UserList->Add(RemoteName);
           LI=UsersListView->Items->Add();
           LI->Caption=RemoteName;
           LI->ImageIndex=-1;
           LI->Indent=-1;
           LI->SubItems->Add("");
           LI->SubItemImages[0]=0;
           LI->SubItems->Add(""Активен"");
        }
        Show=0;
     }
     if (Tmp.Pos("###Here And Inactive###")!=0) {
        if (Tmp.Pos(ComputerName)==0) {
           ChatInputOutput->Lines->Add("Уже в сети: "+RemoteName);
           UserList->Add(RemoteName);
           LI=UsersListView->Items->Add();
           LI->Caption=RemoteName;
           LI->ImageIndex=-1;
           LI->Indent=-1;
           LI->SubItems->Add("");
           LI->SubItemImages[0]=0;
           LI->SubItems->Add(""Неактивен"");
        }
        Show=0;
     }
     if (Tmp.Pos("###Stop###")!=0) {
        if (Tmp.Pos(ComputerName)==0) {
           ChatInputOutput->Lines->Add("Отключился: "+RemoteName);
           if (UserList->IndexOf(RemoteName)!=-1) {
              UsersListView->Items->Delete(UserList->IndexOf(RemoteName));
              UserList->Delete(UserList->IndexOf(RemoteName));
           }
        }
        Show=0;
     }
     if (Tmp.Pos("###Active###")!=0) {
        if (Tmp.Pos(ComputerName)==0) {
           if (UserList->IndexOf(RemoteName)!=-1) {
              LI=UsersListView->Items->Item[UserList->IndexOf(RemoteName)];
              LI->SubItems->Strings[1]=""Активен"";
           }
        }
        Show=0;
     }
     if (Tmp.Pos("###Inactive###")!=0) {
        if (Tmp.Pos(ComputerName)==0) {
           if (UserList->IndexOf(RemoteName)!=-1) {
              LI=UsersListView->Items->Item[UserList->IndexOf(RemoteName)];
              LI->SubItems->Strings[1]=""Неактивен"";
           }
        }
        Show=0;
     }
     if (Tmp.Pos("###Activate###")!=0) {
        TrayIcon->Restore();
        MediaPlayer->FileName=ADirectory+"Call.wav";
        MediaPlayer->Open();
        MediaPlayer->Play();
        Show=0;
     }
     if (Tmp.Pos("###ChatMessage###")!=0) {
        Message=Tmp.SubString(Tmp.Pos(")")+2,Tmp.Length()-Tmp.Pos(")")-1);
     }
     if (Tmp.Pos("###PrivateMessage###")!=0) {
        Message=Tmp.SubString(Tmp.Pos(")")+2,Tmp.Length()-Tmp.Pos(")")-1);
        SS->Position=0;
        SS->WriteString(Message);
        SS->Position=0;
        ShowMessageForm->MessageOutput->Lines->LoadFromStream(SS);
        TrayIcon->Restore();
        MediaPlayer->FileName=ADirectory+"Message.wav";
        MediaPlayer->Open();
        MediaPlayer->Play();
        ShowMessageForm->ShowModal();
        Show=0;
     }
     if (Show==1) {
        ChatInputOutput->Lines->Add(RemoteName+": "+Message);
     }
     if (UsersListView->Items->Count>0) {
        TrayIcon->IconIndex=0;
     } else {
        TrayIcon->IconIndex=1;
     }
     delete SS;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::SendBtnClick(TObject *Sender) {
     UDPServer->Broadcast("###ChatMessage###("+ComputerName+") "+MessageInput->Text,4000);
     MessageInput->Text="";
     MessageInput->SetFocus();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action) {
     UDPServer->Broadcast("###Stop###("+ComputerName+")",4000);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ApplicationEventsException(TObject *Sender, Exception *E) {
     Application->MessageBox("","",MB_OK);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ApplicationEventsActivate(TObject *Sender) {
     UDPServer->Broadcast("###Active###("+ComputerName+")",4000);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ApplicationEventsDeactivate(TObject *Sender) {
     UDPServer->Broadcast("###Inactive###("+ComputerName+")",4000);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ChatInputOutputEnter(TObject *Sender) {
     MessageInput->SetFocus();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::UsersListViewEnter(TObject *Sender) {
     MessageInput->SetFocus();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::UsersListViewContextPopup(TObject *Sender, TPoint &MousePos, bool &Handled) {
     if (UsersListView->ItemIndex!=-1) {
        PopupMenu->Popup(MainForm->Left+UsersListView->Left+MousePos.x,MainForm->Top+UsersListView->Top+MousePos.y+50);
     }
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ApplicationEventsMinimize(TObject *Sender) {
     TrayIcon->Minimize();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::CallMenuItemClick(TObject *Sender) {
     UDPServer->Send(UsersListView->Selected->Caption,4000,"###Activate###("+ComputerName+")");
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::SendMenuItemClick(TObject *Sender) {
     int i,Result;
     TStringStream *Message=new TStringStream("");
     SendMessageForm->UserSelect->Clear();
     SendMessageForm->UserSelect->Items->Add("<Всем пользователям>");
     for (i=1;i<=UserList->Count;i++) {
         SendMessageForm->UserSelect->Items->Add(UserList->Strings[i-1]);
     }
     SendMessageForm->UserSelect->ItemIndex=UsersListView->ItemIndex+1;
     Result=SendMessageForm->ShowModal();
     if (Result==1) {
         SendMessageForm->MessageInput->Lines->SaveToStream(Message);
         Message->Position=0;
         if (SendMessageForm->UserSelect->ItemIndex==0) {
            UDPServer->Broadcast("###PrivateMessage###("+ComputerName+") "+Message->DataString,4000);
         } else {
            UDPServer->Send(UserList->Strings[SendMessageForm->UserSelect->ItemIndex-1],4000,"###PrivateMessage###("+ComputerName+") "+Message->DataString);
         }
     }
     delete Message;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormCreate(TObject *Sender) {
     UserList=new TStringList();
     ComputerName="qwerty";
     UDPServer->Broadcast("###Start###("+ComputerName+")",4000);
     ADirectory=Application->ExeName.SubString(1,Application->ExeName.LastDelimiter("\"));
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormDestroy(TObject *Sender) {
     delete UserList;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::TrayIconRestore(TObject *Sender) {
     MainForm->Show();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ExitMenuItemClick(TObject *Sender) {
     UDPServer->Broadcast("###Stop###("+ComputerName+")",4000);
     Application->Terminate();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::SendAllMenuItemClick(TObject *Sender) {
     int i,Result;
     TStringStream *Message=new TStringStream("");
     SendMessageForm->UserSelect->Clear();
     SendMessageForm->UserSelect->Items->Add("<Всем пользователям>");
     for (i=1;i<=UserList->Count;i++) {
         SendMessageForm->UserSelect->Items->Add(UserList->Strings[i-1]);
     }
     SendMessageForm->UserSelect->ItemIndex=0;
     Result=SendMessageForm->ShowModal();
     if (Result==1) {
         SendMessageForm->MessageInput->Lines->SaveToStream(Message);
         Message->Position=0;
         if (SendMessageForm->UserSelect->ItemIndex==0) {
            UDPServer->Broadcast("###PrivateMessage###("+ComputerName+") "+Message->DataString,4000);
         } else {
            UDPServer->Send(UserList->Strings[SendMessageForm->UserSelect->ItemIndex-1],4000,"###PrivateMessage###("+ComputerName+") "+Message->DataString);
         }
     }
     delete Message;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::MediaPlayerNotify(TObject *Sender) {
     MediaPlayer->Close();
}
//---------------------------------------------------------------------------

Unresolved external

The unresolved external in your case, seems to be because the compiler is unable to find the path to the package data. You should find out if:

  • The path exists in the compiler search path list.
  • The package exists in the default package directory.

If one of them is true then the path isn’t the problem. However as Riho also mentions this is the most likely cause for the problem. The Embarcadero documentation wiki states the following about the unresolved external error:

The named symbol is referenced in the given module but is not defined anywhere in the set of object files and libraries included in the link. Check to make sure the symbol is spelled correctly.

You will usually see this error from the linker for C or C++ symbols if any of the following occur:

  • You did not properly match a symbol’s declarations of __pascal and __cdecl types in different source files.
  • You have omitted the name of an object file your program needs. You need to manually add all required packages to the Requires list.
  • You did not link in the emulation library.

If you are linking C++ code with C modules, you might have forgotten to wrap C external declarations in extern “C”.

You could also have a case mismatch between two symbols.

Source: Unresolved external ‘symbol’ referenced from ‘module’.

Since it seems from the — although altered class names — it is not the case of a misspelling. You also state that you have added the package to the requires list so we rule out this as well. Since you are not linking to C modules we can omit that part as well. So it points to problems with the directory.

About the other questions

Your questions are all really interesting and many of the questions are questions I my self has been looking for answers for when I started developing packages and components for C++ Builder.

Are packages reliable using C++?

Packages are a fine solution to use for C++ Builder, Both C++ Builder is built to support packages and the Pascal written VCL framework. This means that certain implementations are different in C++ Builder than other compilers. This is a necessity to keep the language compatible with its Delphi sibling. For this reason you can use packages in C++ Builder almost as easily as if using Delphi.

Is linking to the first package by adding a reference to its BPI correct?

To start with the second part of your question here, using a lib file makes your package larger simply because it is using static linking — so your guess is correct. Now back to the first part of the question, linking to a package is fine by adding a reference to its BPI. But you do need to make sure that the path variable has been set correctly as Riho suggests in his answer.

Personally I always make sure to my packages to the proper directories in your users folder, the location of this is depending on your Delphi version and operating system version. As far as I recall it is under the Document and Settingsall usersshared documentsRad studio(version number)Packages but I could be mistaken about that.

Can we use the PACKAGE directive only on TObject-derived classes?

The PACKAGE macro is resolved into __declspec(package), you can compare it to __declspec(dllexport). The difference between these is that package is used when declared in a package, and dllexport is used when declared in a DLL. There is a topic about this on the official embarcadero forums titled __declspec(package) vs __declspec(dllexport). The author of the original post, also asks your exact question about this, but unfortunately that part of the question is unanswered.

I have a theory however, and I must emphasize that it is nothing more than a theory. Remy Lebeau writes as a response to the question in the forum post:

__declspec(dllexport) can be used for plain functions, data variables, and
non-VCL classes, and can be used in plain DLLs. __declspec(package) is
used for VCL components, and can only be used with packages.

So from reading his response it seems to me that package is simply exporting the class, just like dllexport does. And since dllexport as far as I can read from his response is to be used in plain DLLs only you have to use the package for exporting (even) non VCL classes from a package.

What is interesting about all this, is that a package is essentially a DLL as far as I recall, but I must admit I can’t find or remember the source of that information so take with a grain of salt.

Is splitting code into packages the best way to achieve the goal of isolating code?

Packages have some very prominent strengths when creating reusable components for the VCL. Obviously using packages limits the user to use either C++Builder or Delphi, but for components written to take advantage of the VCL framework it’s an excellent choice. Properly written packages can ease the reusability of components, and I believe it is the preferred method of distributing components for the VCL.

However if your code does not take advantage of the VCL framework in any way, I would consider using an ordinary library, either static or dynamic, simply to create a more cross compiler friendly approach.

Whether there are any better approach to isolating your code, really depends on the project you are working on. I like to keep code that communicates through use of VCL classes in packages, but code that does not require use of any VCL classes in regular libraries. Keep in mind though that you can easily use VCL classes in a DLL but you need to handle special cases if you choose to export functions with VCL String classes as parameters or return values.

Any general words of advice?

I’m not the most experienced developer of packages myself, but I have found that disabling runtime linking often solves a lot of my problems, while it is somewhat trivial to fix any problems for your own code, you can often run into 3rd party components that have trouble dealing with this. Having said that, I’m not a fan of distributing my packages along with my application as is required in this case. But to be honest that is a matter of taste.

Personally I found it difficult to find some proper answers to many of my questions, when I started creating components and packages. The official helpfile is not the most informative on the matter, but looking through the VCL source code, will often give you the best answer to your question. Besides there is a few other websites that can provide help, many of the sites are targeting Delphi though, but this you have to get used to though.

Delphi Wikia has some good articles about creating components, in particular Creating Components and Creating Packages There is also BCB Journal which is one of the few C++ Builder specific sites, it has some fine articles and an acceptable forum. The Delphi pages at About.com is also a good source of information, I’ve found lots of good hints and nice to knows there, in particular: Creating Custom Delphi Components — Inside and Out.

Ошибки вот такие:

[Linker Error] Unresolved external ‘Ibdatabase::TIBDatabase::’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibdatabase::TIBDatabase::TIBDatabase(Classes::TComponent *)’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘Ibdatabase::TIBTransaction::’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibdatabase::TIBTransaction::TIBTransaction(Classes::TComponent *)’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘Ibquery::TIBQuery::’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibquery::TIBQuery::TIBQuery(Classes::TComponent *)’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibdatabase::TIBDatabase::SetDefaultTransaction(Ibdatabase::TIBTransaction *)’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibdatabase::TIBDatabase::SetDatabaseName(const System::AnsiString)’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibdatabase::TIBTransaction::SetDefaultDatabase(Ibdatabase::TIBDatabase *)’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibdatabase::TIBTransaction::SetActive(bool)’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibcustomdataset::TIBCustomDataSet::SetDatabase(Ibdatabase::TIBDatabase *)’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibcustomdataset::TIBCustomDataSet::SetTransaction(Ibdatabase::TIBTransaction *)’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Db::TDataSet::Next()’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Db::TDataSet::Prior()’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Db::TDataSet::FieldByName(const System::AnsiString)’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibdatabase::TIBTransaction::Commit()’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibdatabase::TIBDatabase::~TIBDatabase()’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Db::TCustomConnection::~TCustomConnection()’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibdatabase::TIBTransaction::~TIBTransaction()’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibquery::TIBQuery::~TIBQuery()’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Ibcustomdataset::TIBCustomDataSet::~TIBCustomDataSet()’ referenced from E:BASEUNIT1.OBJ

[Linker Error] Unresolved external ‘__fastcall Db::TDataSet::~TDataSet()’ referenced from E:BASEUNIT1.OBJ

Компоновщик C ++ Builder предупредит вас, когда вы смешиваете объектные файлы, связанные классическим и clang вместе, помогая вам избежать ошибок компоновщика или времени выполнения.

Сегодня, в 2020 году, мы рекомендуем использовать современные компиляторы Clang, особенно с той работой, которую мы проделали для Win64 (например, совершенно новый отладчик), и улучшениями RTL, чтобы упростить обновление с классической версии. Однако многие клиенты обновляются поэтапно: сначала с классического Win32 до Clang Win32, а затем добавление Win64. Фактически, мы часто прямо рекомендуем это как стратегию обновления, чтобы сначала перейти на Clang, а затем на Win64, в два этапа.

Однако при переходе от классических компиляторов к clang возникает общая проблема. Объектные файлы (библиотеки .obj и .lib), созданные классическим компилятором Win32 и компилятором Clang, не совместимы друг с другом на двоичном уровне. (И classic, и clang могут связываться с Delphi, но classic и clang не могут связываться друг с другом.) Если вы попытаетесь создать приложение, в котором некоторые части построены с помощью Clang, а некоторые — с классическим смешением, вы можете ожидать чего угодно от ошибок компоновщика. к нестабильности во время выполнения. Тем не менее, это легко сделать случайно, как при обновлении, так и при добавлении новой библиотеки или EXE в ваш проект.

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

Прежде чем показать решение, давайте кратко рассмотрим, что может произойти, если в ваших сборках есть эта ошибка.

Проблемы при несовпадении компиляторов

В версии 10.3.3 и новее вы получите предупреждение компоновщика — см. Ниже — перед любым из следующих событий. Но если вы используете старую версию, до того, как мы добавили предупреждение, диагностирующее проблему, вы могли увидеть только следующие ошибки. Они появляются при связывании приложения.

Ошибки времени компоновки

Когда приложение, созданное с помощью цепочки инструментов Clang, связано с классической библиотекой, вы можете увидеть следующие ошибки:

[ilink32 Error] Error: Unresolved external ‘__InitExceptBlockLDTC’

[ilink32 Error] Error: Unresolved external ‘_ThrowExceptionLDTC’

Error: Unresolved external ‘_CatchCleanup()’

Когда приложение, созданное с помощью классической цепочки инструментов, связано с библиотекой, созданной с помощью Clang, вы можете увидеть следующие ошибки:

Error: Unresolved external ‘___seh_personality_v0’

Error: Unresolved external ‘__Unwind_SjLj_Register’

Error: Unresolved external ‘std::_Xbad_alloc()’

Error: Unresolved external ‘___cxa_begin_catch’

Error: Unresolved external ‘___cxa_rethrow’

Error: Unresolved external ‘___cxa_end_catch’

Error: Unresolved external ‘__Unwind_SjLj_Unregister’

Error: Unresolved external ‘__Unwind_Resume’

Error: Unresolved external ‘___cpp_terminate’

Ошибки времени выполнения

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

Не рекомендуется иметь странные ошибки компоновщика или странное поведение во время выполнения. Поэтому мы добавили предупреждение, чтобы проверить эту ситуацию.

Диагностика: предупреждение о новом компоновщике

RAD Studio / C ++ Builder 10.3.3 и новее предупреждает вас о смешивании clang и classic при компоновке. (Если возникают ошибки компоновщика, подобные описанным выше, это предупреждение выдается перед ними, поэтому вы увидите предупреждение перед любыми ошибками из-за проблемы.)

В сообщении говорится: «Предупреждение: несоответствие компилятора». а затем сообщает, что он ожидал и что обнаружил:

Warning: Compiler mismatch. Module ‘Z:RAD STUDIO PROJECTSDEMOS AND WEBINARSMIXING CLASSIC AND CLANGWIN32DEBUGMYSTATICLIB.LIB|Unit1’ built with bcc32 compiler; expected the bcc32c compiler because of ‘Z:RAD STUDIO PROJECTSDEMOS AND WEBINARSMIXING CLASSIC AND CLANGWIN32DEBUGVCLAPP.OBJ’

Итак, как компоновщик проверяет смешанные объекты и как он узнает, чего ожидать?

В приведенной выше ошибке у меня есть приложение VCL, связывающееся в статической библиотеке. Приложение VCL создано с помощью Clang. Библиотека построена на классическом. Приложение clang ссылается на библиотеку с помощью:

#pragma comment(lib, «MyStaticLib»)

see documentation on linking with #pragma comment vs #link.

Ошибиться в несовпадении компиляторов очень легко. Как вы можете видеть на скриншоте справа, вы не можете легко определить, какой компилятор Win32 используется. Это то, что мы могли бы улучшить, но сейчас в нем указана целевая платформа, а не компилятор.

Теперь наш компилятор передает в каждый объект запись (небольшой фрагмент данных), в которой говорится, с каким компилятором он был построен (например, Clang Win32). При компоновке компоновщику предоставляется набор объектных файлов и библиотек в порядке, указанном в команде. линия. Он смотрит на первый объект, с которым связывается, и отмечает, что ожидает, что все последующие объекты будут построены с тем же компилятором, что и этот первый. Для каждого объекта, с которым он связан (и учитывая библиотеку, которая представляет собой просто набор объектов для каждого объекта в библиотеке), он проверяет, был ли он построен с помощью ожидаемого компилятора.

В противном случае выдается указанное выше предупреждение, которое вы также можете увидеть на изображении справа. Вы можете видеть, что он перечисляет ошибочный объект и то, с чем он был построен, а также объясняет, почему он искал другой компилятор. Это предназначено, чтобы помочь вам диагностировать настройку сборки.

TLDR

Краткое резюме: объединение объектных файлов, созданных двумя компиляторами, в один двоичный файл — плохая идея. Компоновщик выдаст вам предупреждение, если вы это сделаете, и расскажет, что для чего построено, чтобы вы могли это исправить. Это устраняет проблемы компоновщика и проблемы со стабильностью приложения!

Дальнейшее чтение

Компоненты упаковки или библиотеки, написанные на классических и Clang компиляторах Win32 C ++ На
этой новой странице документации обсуждается предупреждение компоновщика, но также содержится немного больше информации. В нем рассматривается, как использовать clang или классические двоичные файлы, если вы разработчик приложений и создаете приложения с несколькими частями (возможно, связываясь с библиотекой C ++ с открытым исходным кодом, которую вы также создаете), а также есть еще один раздел для библиотеки разработчик (например, написание компонентов или библиотек и распространение их среди клиентов.)


Register for Python GUI Apps Con 2023 today!


Laus

Гость


Подскажите, пожалуйста, что обозначают ошибки

[Linker Error] Unresolved external ‘TDeck<Body *>::~TDeck<Body *>()’ referenced from C:PROGRAM FILESBORLANDCBUILDER6PROJECTSРАЗРАБОТКАИГРЫЧЕРВЬMODWORM.OBJ

[Linker Error] Unresolved external ‘TDeck<Body *>::TDeck<Body *>()’ referenced from C:PROGRAM FILESBORLANDCBUILDER6PROJECTSРАЗРАБОТКАИГРЫЧЕРВЬMODWORM.OBJ

[Linker Error] Unresolved external ‘TDeck<Body *>::AddLeft(Body *)’ referenced from C:PROGRAM FILESBORLANDCBUILDER6PROJECTSРАЗРАБОТКАИГРЫЧЕРВЬMODWORM.OBJ

и как от них избавиться.

TDeck<Body *> — шаблон дека (стек + очередь)
MODWORM.h (MODWORM.cpp) — разрабатываемый класс, в нём используется описание TDeck<Body *> body.

template <class T> class TDeck
{
  …
  TDeck();
  ~TDeck();
  void AddLeft(T inf);
  void AddRight(T inf);
  …
};

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


Записан
npak

Команда клуба

ru
Offline Offline
Пол: Мужской


Laus, эти ошибки означают, что ни в объектных файлах, ни в библиотеках не обнаружены тела методов

TDeck<Body *>::~TDeck<Body *>()
TDeck<Body *>::TDeck<Body *>()
TDeck<Body *>::AddLeft(Body *)

В заголовочном файле указаны декларации — имена методов и типы параметров.  В заголовочном файле отсутствуют тела методов.  Более того, они отсутствуют во всех файлах, которые обработал линкер.  О чём он и сообщил этими ошибками.  Единственный способ их исправить — написать указанные методы (или найти библиотеку, в которой они реализованы).


Записан

lapulya

Молодой специалист

ru
Offline Offline


Тут дело то в чем… видимо реализация этих методов (членов) находится в отдельном (я так подозреваю *.cpp файле) а описание в файле заголовка типа (в *.h файле) но это линьковаться не будет потому как насколько мне известно настоищие компиляторы этого делать НЕ умеют, хотя стандартом это помоему разрешено


Записан

С уважением Lapulya

grozny

Гость


надо тела ф-ций-членов шаблона определять не в отдельном .срр, а рядом с определением шаблона же, в .h. По крайней мере, в визуальном С++ 7.1 всё ещё не понимают членов шаблона в отдельном .срр. Т.к. ф-ции-члены шаблонов связываются на этапе компиляции, а не линковки, то у компилятора должно быть определение этих ф-ций в каждом файле, где используется шаблон. Проще всего добиться этого поместив тело ф-ции-члена прямо в описание шаблона.

Печальное исключение из правил хорошего стиля, напоминающее о том, что шаблоны — суть те же макросы.


Записан
lapulya

Молодой специалист

ru
Offline Offline


то grozny, хех

надо тела ф-ций-членов шаблона определять не в отдельном .срр, а рядом с определением шаблона же, в .h.

я это и имел ввиду, просто уверенности, что человек допустил именно эту ошибку не было…
а про это

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

то стандарту, а точнее коммиссии которая его принимает, глубоко по барабану (ну или почти) все реализации компиляторов и их сложность в узких вопросах (типа этого), поэтому не все что написано в стандарте реализовано.


Записан

С уважением Lapulya

Laus

Гость


В Builder’е 6.0 реализован достаточно удобный интерфейс: в ClassExplorer’е генерируется список всех переменных и функций класса, при этом нажав правую кнопку мыши на названии функции можно переходить к её объявлению или реализации (по выбору). Но это работает только в том случае, если разделить реализацию и объявление функций в одноимённые файлы  *.cpp и *.h соответственно и то не всегда  Улыбаюсь .
Можно обойти эту проблему, если Builder сам генерирует по файлу с заголовком (*.h)  «каркас» для cpp-файла.
Как сделать то же, но руками — не понятно   Так больше нельзя... .
Так что вносить реализацию функций-членов в файл заголовков — не лучший выход.


Записан
godlsd

Гость


Сам пыхтел над этой проблемой… и заметил особенность(BorlandC++)если создавать cpp файл нормальным способом через меню компилятора, а не вручную, то всё прекрасно работает!!!


Записан
lapulya

Молодой специалист

ru
Offline Offline


Ага…

….через меню компилятора…

начало не плохое…


Записан

С уважением Lapulya

Понравилась статья? Поделить с друзьями:

Не пропустите эти материалы по теме:

  • Яндекс еда ошибка привязки карты
  • Ошибка unrecognized game client
  • Ошибка unrecognized arguments
  • Ошибка unreal engine fortnite
  • Ошибка unreal engine 4 crash reporter как исправить

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии