/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
En uventet Unresolved External
Fra : Daniel Kjøller Skove~


Dato : 01-06-02 18:28

Jeg får en "Unresolved external"-fejl når jeg linker mit program.
Funktionerne burde findes i en dll-fil, som fulgte med SDK'et (der var kun 1
DLL-fil, så der er den rigtige, også ifølge dokumentationen). Jeg har brugt
ImpLib.exe til at lave en lib-fil og linket lib-filen sammen med programmet
som jeg har gjort det 1000 gange før med andre projekter. Hvad kan der være
galt?

Jeg bruger iøvrigt følgende kommando:
C:\BCC55\Bin\ilink32.exe /Lc:\bcc55\lib;c:\bcc55\lib\psdk;c:\ifc\lib /aa
C0W32.OBJ main.obj, test.exe,, IMPORT32.LIB ifc.lib CW32.LIB
Det er i ifc.lib, funktionerne burde være.





 
 
Mogens Hansen (01-06-2002)
Kommentar
Fra : Mogens Hansen


Dato : 01-06-02 19:01


"Daniel Kjøller Skovenborg" <waldeinburg@yahoo.com> wrote

[snip]
> Det er i ifc.lib, funktionerne burde være.
>

Prøv at bruge "tdump.exe" til at se hvilke funktioner der er i "ifc.lib" og
sammenhold det med navnene på de unresolved externals.

Venlig hilsen

Mogens Hansen



Daniel Kjøller Skove~ (01-06-2002)
Kommentar
Fra : Daniel Kjøller Skove~


Dato : 01-06-02 21:32

> Prøv at bruge "tdump.exe" til at se hvilke funktioner der er i "ifc.lib

Det har jeg så prøvet (så lærte jeg det. Tak).

her er noget af det, jeg fik ud af det:

Error: Unresolved external 'CImmMouse::Initialize(void *, void *, unsigned
long, int)' referenced from MAIN.OBJ

og i lib-filen findes:

010870 THEADR ?Initialize@CImmMouse@@QAEHPAX0KH@Z
010898 COMENT Purge: Yes, List: Yes, Class: 160 (0A0h), SubClass: 1 (01h)
Dynamic link import (IMPDEF)
Imported by: ordinal
Internal Name: ?Initialize@CImmMouse@@QAEHPAX0KH@Z
Module Name: IFC23.dll
ordinal: 517
0108D0 COMENT Purge: Yes, List: Yes, Class: 251 (0FBh), SubClass: 3 (03h)
Hint:516
0108D9 MODEND

En anden fejl så sådan ud:

Error: Unresolved external '_GUID_Feelit_Sine' referenced from MAIN.OBJ
Søgning på "Sine" i teksten fra TDump gav ingen resultat.

Resten fejlene var destructore. Eksempel:

Error: Unresolved external 'CImmMouse:CImmMouse()' referenced from
MAIN.OBJ

Ingen af søgningerne på @CImmMouse gav et resultat, der kunne være en
destructor. Står de på en anden måde?

Den første fejl, der spyttes ud fra linkeren, er omkring en destructor. Kan
det være, de resterende, som faktisk findes i lib-filen, går galt pga. det?



Ivan Johansen (01-06-2002)
Kommentar
Fra : Ivan Johansen


Dato : 01-06-02 22:25

Daniel Kjøller Skovenborg wrote:

> Error: Unresolved external 'CImmMouse::Initialize(void *, void *, unsigned
> long, int)' referenced from MAIN.OBJ
>
> og i lib-filen findes:
>
> 010870 THEADR ?Initialize@CImmMouse@@QAEHPAX0KH@Z

Din DLL indeholder klasser. Det ser ikke ud som om den er kompileret med
Borlands kompiler. DLL'er med klasser er ikke kompatible mellem
forskellige kompilere. Du læse om mulige løsninger her:
http://bcbdev.com/articles/vcdll2.htm

Ivan Johansen


Ivan Johansen (01-06-2002)
Kommentar
Fra : Ivan Johansen


Dato : 01-06-02 22:27

Daniel Kjøller Skovenborg wrote:

> Error: Unresolved external 'CImmMouse::Initialize(void *, void *, unsigned
> long, int)' referenced from MAIN.OBJ
>
> og i lib-filen findes:
>
> 010870 THEADR ?Initialize@CImmMouse@@QAEHPAX0KH@Z

Din DLL indeholder klasser. Det ser ikke ud som om den er kompileret med
Borlands kompiler. DLL'er med klasser er ikke kompatible mellem
forskellige kompilere. Du kan læse om mulige løsninger her:
http://bcbdev.com/articles/vcdll2.htm

Ivan Johansen


Daniel Kjøller Skove~ (01-06-2002)
Kommentar
Fra : Daniel Kjøller Skove~


Dato : 01-06-02 22:35

> Du kan læse om mulige løsninger her:
> http://bcbdev.com/articles/vcdll2.htm

Det er jeg ked af at se:
(citat) All three of my techniques require that you have Microsoft Visual
C++.
Eftersom jeg ikke er i besiddelse af Visual C++ hjælper det mig ikke.
Er der virkelig ingen udvej?



Ivan Johansen (01-06-2002)
Kommentar
Fra : Ivan Johansen


Dato : 01-06-02 23:03

Daniel Kjøller Skovenborg wrote:

> Det er jeg ked af at se:
> (citat) All three of my techniques require that you have Microsoft Visual
> C++.
> Eftersom jeg ikke er i besiddelse af Visual C++ hjælper det mig ikke.
> Er der virkelig ingen udvej?


Nej, du skal enten bruge source-koden eller den kompiler, som blev brugt
til at lave DLL'en. Netop af den grund bør man undgå klasser i DLL'er.
Msåke kan du få dem, der har lavet den til at kompilere den med Borlands
kompiler eller lave et C interface til den.

Ivan Johansen



Mogens Hansen (02-06-2002)
Kommentar
Fra : Mogens Hansen


Dato : 02-06-02 05:59


"Daniel Kjøller Skovenborg" <waldeinburg@yahoo.com> wrote

> Eftersom jeg ikke er i besiddelse af Visual C++ hjælper det mig ikke.
> Er der virkelig ingen udvej?

Visual C++ er sikkert den nemmeste måde at løse opgaven på (fordi den har
SDK og RTL med), men du kan også bruge Intel C++.
Man kan downloade en 60 dages trial udgave (www.intel.com), men husk lige at
læse licensbetingelserne. Man må formodentlig ikke distribuere det som man
har oversat med trial udgaven.

Venlig hilsen

Mogens Hansen



Daniel Kjøller Skove~ (02-06-2002)
Kommentar
Fra : Daniel Kjøller Skove~


Dato : 02-06-02 13:11

Er det muligt, at bruge de rigtige navne i min source-code ved hjælp af
LoadLibrary og derefter nogle kald til GetProcAddress, hvor man jo bruger
det navn, der står i DLL'en? Jeg ville kunne gøre det, hvis det var
C-funktioner, men kan det også lade sig gøre med funktioner i klasser?



Ivan Johansen (02-06-2002)
Kommentar
Fra : Ivan Johansen


Dato : 02-06-02 13:28

Daniel Kjøller Skovenborg wrote:

> Er det muligt, at bruge de rigtige navne i min source-code ved hjælp af
> LoadLibrary og derefter nogle kald til GetProcAddress, hvor man jo bruger
> det navn, der står i DLL'en? Jeg ville kunne gøre det, hvis det var
> C-funktioner, men kan det også lade sig gøre med funktioner i klasser?


Nej, for det er ikke bare funktioner. Selv om du kan få adressen på en
funktion, hvordan vil du kalde den? Hvad vil du sende med som instans af
klassen? Desuden er der forskellige implementationsdetaljer for klasser
i forskellige kompilere. Der er desværre ikke nogen nem løsning.

Ivan Johansen



Desilva (07-06-2002)
Kommentar
Fra : Desilva


Dato : 07-06-02 20:46

> Din DLL indeholder klasser. Det ser ikke ud som om den er kompileret med
> Borlands kompiler. DLL'er med klasser er ikke kompatible mellem
> forskellige kompilere.

Gælder dette også hvis man bruger en factory funktion til at generere ens
objekter?
I så fald burde det vel være ligegyldigt hvilken kompiler der lavede
dll'en...eller?



Mogens Hansen (07-06-2002)
Kommentar
Fra : Mogens Hansen


Dato : 07-06-02 21:14


"Desilva" <alamyx@softhome.net> wrote

> > Din DLL indeholder klasser. Det ser ikke ud som om den er kompileret med
> > Borlands kompiler. DLL'er med klasser er ikke kompatible mellem
> > forskellige kompilere.
>
> Gælder dette også hvis man bruger en factory funktion til at generere ens
> objekter?

Det er stort set det COM gør.

> I så fald burde det vel være ligegyldigt hvilken kompiler der lavede
> dll'en...eller?
>

Nej ikke generelt.
Hvis man blander binære resultater oversat med forskellige compilere skal de
være binært kompatible - ihvert fald inden for de egenskaber man bruger i
interfacet.
Hvis begge compilere kan anvendes til at skrive COM komponenter med, kan det
sikkert lade sig gøre, men man skal holde sig inden for de begrænsninger som
COM har - f.eks.
* Ikke smide exceptions
* Kun bruge virtuelle metoder
* Ingen multipel arv i typen der returneres
* Ingen brug af dynamic_cast (prøv det, og du vil blive behørigt straffet
fordi du løj da du castede din VOID** i QueryInterface!)
* Ingen virtuelle base klasser
* Begrænset udvalg af funktions parameter typer.
F.eks. ingen double
Kun pointer til objekter der overholder begrænsningerne nævnt her -
altså f.eks. ingen const std::string& eller std::vector
Og der er sikker flere regler.


Venlig hilsen

Mogens Hansen



Mogens Hansen (01-06-2002)
Kommentar
Fra : Mogens Hansen


Dato : 01-06-02 22:36


"Daniel Kjøller Skovenborg" <waldeinburg@yahoo.com> wrote

>
> Error: Unresolved external 'CImmMouse::Initialize(void *, void *, unsigned
> long, int)' referenced from MAIN.OBJ
>
> og i lib-filen findes:
>
> 010870 THEADR ?Initialize@CImmMouse@@QAEHPAX0KH@Z
> 010898 COMENT Purge: Yes, List: Yes, Class: 160 (0A0h), SubClass: 1 (01h)
> Dynamic link import (IMPDEF)
> Imported by: ordinal
> Internal Name: ?Initialize@CImmMouse@@QAEHPAX0KH@Z
> Module Name: IFC23.dll
> ordinal: 517
> 0108D0 COMENT Purge: Yes, List: Yes, Class: 251 (0FBh), SubClass: 3 (03h)
> Hint:516
> 0108D9 MODEND
>
> En anden fejl så sådan ud:
>
> Error: Unresolved external '_GUID_Feelit_Sine' referenced from MAIN.OBJ
> Søgning på "Sine" i teksten fra TDump gav ingen resultat.
>

Du må finde ud af hvor den stammer fra

> Resten fejlene var destructore. Eksempel:
>
> Error: Unresolved external 'CImmMouse:CImmMouse()' referenced from
> MAIN.OBJ
>
> Ingen af søgningerne på @CImmMouse gav et resultat, der kunne være en
> destructor. Står de på en anden måde?
>

Jeg gætter på at den hedder noget med ??1CImmMouse...

> Den første fejl, der spyttes ud fra linkeren, er omkring en destructor.
Kan
> det være, de resterende, som faktisk findes i lib-filen, går galt pga.
det?
>

Nej.
Problemet er at det DLL, du vil anvende er C++ kode skrevet med Microsoft
Visual C++ (eller en binært kompatibel med samme name-mangling - f.eks.
Intel C++), og du prøver at bruge det i et program skrevet med Borland C++.
Det kan man generelt ikke - de er ikke binært kompatible.
Hvis det tidligere er gået godt for dig, er det fordi du har brugt et C
interface.

Du har flere (ikke helt trivielle) muligheder:
* Hvis du har sourcen til DLL'et:
* Oversæt sourcen med Borland C++ - og link den statisk med dit program
* Oversæt sourcen med Borland C++ - og lav et DLL med et andet navn
* Brug funktionaliteten via et C interface (nemt) - hvis det findes
* Brug funktionaliteten via et COM interface (lidt sværere) - hvis det
findes
* Skriv dit program med Microsoft Visual C++ eller Intel C++

Det jeg plejer at gøre, når ovenstående ikke er muligt, er at skrive et
ekstra DLL med Microsoft Visual C++ eller Intel C++, der eksporterer
funktionaliteten som C funktioner.
Oven på det laves et identisk objekt-orienteret interface, som oversættes
med Borland compileren og linkes statisk med programmet.

Altså

------------
| BAR.EXE| <- Oversat med BCC
------------
|
---------------
|C_FOO.DLL| <- Oversat med MSVC
---------------
|
-------------
| FOO.DLL | <- Oversat med MSVC
-------------

hvor FOO.DLL indeholder

class foo
{
public:
foo(int arg1, const char* arg2);
~foo();

int foo_func1(int arg1);
};


C_FOO.DLL indeholder
extern "C"
{
typedef void* foo_handle;
foo_handle create_foo(int arg1, const char* arg2);
destroy_foo(foo_handle* foo_arg);
int foo_foo_func1(foo_handle* foo_arg, int arg1);
}

og BAR.EXE bruger header-filen

class foo
{
public:
foo(int arg1, const char* arg2) :
handle_(create_foo(arg1, arg2)) {}
~foo()
{ destroy_foo(handle_); }
int foo_func1(int arg1)
{ return foo_foo_func1(handle_, arg1); }

private:
foo_handle handle_;

private:
// take care of copy-constructor
// and assignment operator
};

(Ovenstående er _ikke_ oversat og testet!)
PS. Brug kun kompatible datatyper i interface - altså dem som Win32 API også
bruger!
Ikke noget med float, double, og slet ikke klasser som std::vector,
std::string etc.

Venlig hilsen

Mogens Hansen





Daniel Kjøller Skove~ (03-06-2002)
Kommentar
Fra : Daniel Kjøller Skove~


Dato : 03-06-02 21:51

Jeg fører lige spørgsmålet lidt videre, selvom problemet ikke er helt det
samme.

Jeg fik løst det andet problem ved at bede firmaet om en Borland-kombitabel
DLL (jeg var så heldig, at de havde en under udvikling og kunne maile en
endnu ikke udgivet beta-version).
Der er dog stadig en enkel Unresolved external, som jeg stadig får:

Error: Unresolved external '_GUID_Feelit_Sine' referenced from MAIN.OBJ

Jeg bruger GUID_Feelit_Sine, som er defineret med DEFINE_GUID i en af
headerne. DEFINE_GUID er defineret sådan her:

#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID DECLSPEC_SELECTANY name \
= { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }

Altså et eller andet eksternt (jeg er ikke ekspert, men det må det vel
betyde), som sikkert skulle ligge i den DLL, jeg har fået (jeg prædiker
sikkert for en præst nu :-/). GUIDs har heller ikke voldet mig problemer
før.

Den er ikke værre, end at jeg kan oprette den internt:

GUID const Sine = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } };

Dog synes jeg, det kunne være interresant at vide, hvad der er galt nu, og
om der er en fare ved den måde, jeg løser problemet på.



Søg
Reklame
Statistik
Spørgsmål : 177496
Tips : 31968
Nyheder : 719565
Indlæg : 6408491
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste