Toon posts:

[Visual C++ 2005] DLL Link: unresolved token

Pagina: 1
Acties:
  • 693 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Hallo,

Ik zit nu al een tijdje te prutsen, en ik kan het maar niet werken krijgen. Ik heb een DLL gemaakt in Visual C++ 2005 (CLR Class Library), en heb dan een ander project (CLR Windows Forms Application) waar ik een functie uit die DLL wil gebruiken. Bijde projecten zitten in 1 solution.

De DLL bestaat uit my_dll.h & my_dll.c (& de standaard troep), hier heb ik dus alleen maar 1 functie aan toegevoegd (die niks doet). Mijn applicatie bestaat uit my_app.c en Form1.h, aan Form1.h heb ik niks veranderd. aan my_app.c heb ik alleen maar 1 regel toegevoegd, nl. de include regel voor de my_dll.h file.

Als ik dit dus probeer te compileren, dan krijg ik 2 errors, nl:
Error 1 error LNK2020: unresolved token (06000005) my_dll.Class1::my_func my_app.obj

Error 2 fatal error LNK1120: 1 unresolved externals E:\!projects\VS.NET Projects\test\test\Release\my_app.exe 1

Ik heb van alles geprobeerd, ik heb op google gezocht, daar staan allemaal verschillende problemen/antwoorden, maar ze helpen allemaal niet.

Alvast bedankt.

hier nog ff de broncode van de bestanden:

my_dll.h:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// my_dll.h

#pragma once

using namespace System;

namespace my_dll {

    public ref class Class1
    {
        // TODO: Add your methods for this class here.
    public:
        static char * my_func(char * my_var);
    };
}


my_dll.c:
C++:
1
2
3
4
5
6
7
8
9
10
// This is the main DLL file.

#include "stdafx.h"

#include "my_dll.h"

char * my_dll::Class1::my_func(char * my_var)
{
    return my_var;
}


my_app.c:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// my_app.cpp : main project file.

#include "stdafx.h"
#include "Form1.h"
#include "../my_dll/my_dll.h"

using namespace my_app;

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
    // Enabling Windows XP visual effects before any controls are created
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false); 

    // Create the main window and run it
    Application::Run(gcnew Form1());
    return 0;
}

[ Voor 0% gewijzigd door RobIII op 02-05-2007 02:38 . Reden: Code-tags toegevoegd ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je moet natuurlijk wel aangeven dat je Class1 uit een andere dll komt. Hoe weet ik even niet uit mijn hoofd, in C++ doe je dat met __declspec(dllimport) bij je class definition, maar wellicht gaat dat in C++/CLI anders (waarschijnlijk met attributes oid)

[ Voor 56% gewijzigd door .oisyn op 02-05-2007 11:04 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Allereerst bedankt voor je antwoord, maar het heeft me niet echt geholpen denk ik. Ik krijg er nu 2 extra warnings bij:

Warning 1 warning C4091: '__declspec(dllexport)' : ignored on left of 'my_dll::Class1' when no variable is declared e:\!projects\vs.net projects\test\test\my_dll\my_dll.h 14

Warning 2 warning C4091: '__declspec(dllimport)' : ignored on left of 'my_dll::Class1' when no variable is declared e:\!projects\vs.net projects\test\test\my_dll\my_dll.h 14

Op internet las ik wel allemaal dingen over een .lib file, maar deze genereert Visual C++ niet voor mij? Ik heb gezocht in de work directory van mijn solution, maar daar is nergens een .lib file te bekennen.

Iemand die mij verder kan helpen? Alvast bedankt.

En dan hier nog ff de up2date code:
my_dll.h:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// my_dll.h

#pragma once

using namespace System;

namespace my_dll {

    MY_DLL_SYMBOL ref class Class1
    {
        // TODO: Add your methods for this class here.
    public:
        static char * my_func(char * my_var);
    };
}


my_dll.cpp
C++:
1
2
3
4
5
6
7
8
9
10
// This is the main DLL file.

#include "stdafx.h"

#include "my_dll.h"

char * my_dll::Class1::my_func(char * my_var)
{
    return my_var;
}


stdafx.h (van my_dll)
C++:
1
2
3
#pragma once

#define MY_DLL_SYMBOL __declspec(dllexport)


my_app.cpp
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// my_app.cpp : main project file.

#include "stdafx.h"
#include "Form1.h"
#include "../my_dll/my_dll.h"

using namespace my_app;

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
    // Enabling Windows XP visual effects before any controls are created
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false); 

    // Create the main window and run it
    Application::Run(gcnew Form1());
    return 0;
}


stdafx.h(van my_app)
C++:
1
2
3
#pragma once

#define MY_DLL_SYMBOL __declspec(dllimport)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je haalt C++ door de war met C++/CLI, dat zijn twee verschillende talen die VC++ allebei ondersteunt. Wellicht dat het in C++/CLI (De .Net 2.0 variant van C++, waarin jij dus werkt) anders werkt.

Overigens lijkt me die warning duidelijk: je past de __declspec toe op de variabelen die je na de class definieert terwijl die er niet zijn. Je moet 'm juist op de class zelf definieren. Vergelijk:

C++:
1
2
3
4
5
6
class A { };   // een class definitie zonder variabel-definities
class B { } b1, b2, b3;  // een class definitie met 3 variabel-definities

__declspec(dllimport) int var;   // dllimport werkt op var
__declspec(dllimport) class Aap { int noot, mies; } var2;   // idem, dllimport werkt op var2
class __declspec(dllimport) Henk { int bert; } var3;  // dllimport werkt nu op Henk, niet op var3

[ Voor 9% gewijzigd door .oisyn op 02-05-2007 13:16 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Ja, ik heb veel geprogrammeerd met C++, en heb wel wat dingen met Visual Basic en Visual C# gedaan, dus ik dacht dat ik zo ff met Visual C++ kon werken. Maja, dat valt tegen dus.

Ik heb in my_dll.h nu het volgende:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// my_dll.h

#pragma once

using namespace System;

namespace my_dll {

    ref class MY_DLL_SYMBOL Class1
    {
        // TODO: Add your methods for this class here.
    public:
        static char * my_func(char * my_var);
    };
}


Zoals jij voorstelde, echter dit geeft weer een aantal problemen, en dat komt blijkbaar door Managed code, waar ik dus bijna geen verstand van heb :P
Error 1 error C3386: 'my_dll::Class1' : __declspec(dllexport)/__declspec(dllimport) cannot be applied to a managed type e:\!projects\vs.net projects\test\test\my_dll\my_dll.h 10
Error 2 error C3395: 'my_dll::Class1::my_func' : __declspec(dllexport) cannot be applied to a function with the __clrcall calling convention e:\!projects\vs.net projects\test\test\my_dll\my_dll.h 13
Error 3 error C3395: 'my_dll::Class1::Class1' : __declspec(dllexport) cannot be applied to a function with the __clrcall calling convention e:\!projects\vs.net projects\test\test\my_dll\my_dll.h 14
Error 4 error C3395: 'my_dll::Class1::Class1' : __declspec(dllexport) cannot be applied to a function with the __clrcall calling convention e:\!projects\vs.net projects\test\test\my_dll\my_dll.h 14
Error 5 error C3386: 'my_dll::Class1' : __declspec(dllexport)/__declspec(dllimport) cannot be applied to a managed type e:\!projects\vs.net projects\test\test\my_dll\my_dll.h 10
Warning 6 warning C4272: 'my_dll::Class1::my_func' : is marked __declspec(dllimport); must specify native calling convention when importing a function. e:\!projects\vs.net projects\test\test\my_dll\my_dll.h 13
Warning 7 warning C4272: 'my_dll::Class1::Class1' : is marked __declspec(dllimport); must specify native calling convention when importing a function. e:\!projects\vs.net projects\test\test\my_dll\my_dll.h 14
Warning 8 warning C4272: 'my_dll::Class1::Class1' : is marked __declspec(dllimport); must specify native calling convention when importing a function. e:\!projects\vs.net projects\test\test\my_dll\my_dll.h 14
Enig idee wat ik hier nog aan moet veranderen?

En dat .lib bestand waar ik het over had in mn vorige post, is dat nodig?

Alvast bedankt!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zoals ik al zei, ik had al een vermoeden dat dat anders werkte in C++/CLI :). Waarschijnlijk moet je het DllImport attribuut toepassen oid.

Overigens, en dat bedenk ik me nu ineens, je hoeft helemaal niet die dll header te includen zoals in C++ gebruikelijk is. Wat je nodig hebt is een #import directive die zorgt dat je de definities van je library in je sourcefile laadt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
#import werkt bij mij ook niet, omdat het niet kan met /clr:pure of /clr:safe op de command line, alleen dat heeft Visual C++ zelf ingesteld.

Is het misschien verstandig om in Visual C++ .NET 2003 te gaan werken? Daar heb ik wel eerder programma's mee gemaakt, heb de installatie DVD nog wel, maar zal het dan wel gaan werken? Dat is gewoon C++ toch? en geen C++/CLI?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

VC++ 2005 kan ook gewoon C++ hoor. Kwestie van een compiler optie omzetten (Project properties -> General -> Common Language Runtime support uitzetten)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Dat is leuk, maar nu vind hij namespace System dus niet. In .NET 2003 werkte ik ook met .NET framework. (1.1 volgens mij)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ja, wil je nou C++ of C++/CLI compilen? C++ is geen .Net, dus logisch dat ie de System namespace dan niet kent. In VS 2003 heette het nog "managed C++" (of "managed extensions for C++" voluit), maar ook dat is geen C++.

Dat het niet kan met /clr:pure of /clr:safe is omdat je met charpointers werkt, die unsafe zijn. Als je strings door wil geven zul je String^ moeten gebruiken, of je moet zeggen dat ie niet pure en niet safe CLR support wilt hebben (dezelfde optie waarmee je ook CLR uit kunt zetten)

[ Voor 30% gewijzigd door .oisyn op 02-05-2007 15:51 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Ah, ik snap het :P

dus, ik heb nu gewoon CLR (/clr) en dus niet pure of safe. Ik heb nu de Class er tussen uit gehaald, want deze had ik eigenlijk niet nodig, die werd er alleen standaard bij gedaan.
Dan heb ik de functie in de header dus gedeclareerd met __declspec(dllexport) en de DLL compileert zonder warnings/errors. Met dumpbin zie ik nu ook daadwerkelijk een functie in mijn dll file zitten.

Echter, nu ik probeer in my_app de DLL op te roepen, krijg ik een melding dat my_func geen member is van my_dll.

Precieze errors:
Error 1 error C2039: 'my_func' : is not a member of 'my_dll' \\kamer\e\!projects\VS.NET Projects\test\test\my_app\my_app.cpp 20
Error 2 error C3861: 'my_func': identifier not found \\kamer\e\!projects\VS.NET Projects\test\test\my_app\my_app.cpp 20
hier maar weer even mijn code:
my_app.cpp
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// my_app.cpp : main project file.

#include "stdafx.h"
#include "Form1.h"
//#include "../my_dll/my_dll.h"
#import "my_dll.tlb"
using namespace my_app;

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
    // Enabling Windows XP visual effects before any controls are created
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false); 

    // Create the main window and run it
    Application::Run(gcnew Form1());

    char *abc = "test";
    abc = my_dll::my_func(abc);
    return 0;
}


stdafx.h (my_dll)
C++:
1
2
3
4
5
6
7
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently

#pragma once

#define MY_DLL_SYMBOL __declspec(dllexport)


my_dll.cpp
C++:
1
2
3
4
5
6
7
8
9
10
// This is the main DLL file.

#include "stdafx.h"

#include "my_dll.h"

char * my_dll::my_func(char * my_var)
{
    return my_var;
}


my_dll.h
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// my_dll.h

#pragma once

using namespace System;

namespace my_dll {
    
    //ref class MY_DLL_SYMBOL Class1
    //{
    //  // TODO: Add your methods for this class here.
    //public:
        char MY_DLL_SYMBOL *my_func(char * my_var);
    //};
}


En dit werkt ook niet voor my_dll.h
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// my_dll.h

#pragma once

using namespace System;

namespace my_dll {
    
    //ref class MY_DLL_SYMBOL Class1
    //{
    //  // TODO: Add your methods for this class here.
    //public:
        MY_DLL_SYMBOL char *my_func(char * my_var);
    //};
}

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Eerlijk gezegd denk ik dat je die __declspec niet nodig hebt, want volgens mij worden .Net classes standaard al geexporteerd. Alleen ondersteunt .Net vziw geen losse functies, je class is dus wel nodig.

.edit: ik heb het even geprobeerd, en bij mij werkt het gewoon. Gebruik je originele code zoals in de topicstart, maar dan zonder de #include my_dll.h. Voeg je my_dll toe als reference aan je project (project -> references...), en dan hoef je ook niets te includen of te importen, en dan werkt het automagisch.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Het compileren werkt dan ja, maar als ik probeer de .exe op te starten, dan krijg ik een error melding dat ie niet kan starten, en als ik um dan debug, dan krijg ik een melding dat hij de assembly van my_app of een dependency niet kan vinden. Ik heb my_app.exe en my_dll.dll in dezelfde directory staan. En dat het misschien geen .NET dll is.

Kun jij wel jouw programma opstarten?

Verwijderd

Topicstarter
Ik heb het probleem al opgelost, ik starte het programma via het netwerk (\\computer\d\my_app.exe) en de dll was ook in die map, alleen dat kon het .NET framework dan niet loaden denk ik. Als ik bijde bestanden bijv. op mn bureaublad neerzet en het dan opstart dan werkt het wel.

Hartelijk dank voor je oplossing !!
Pagina: 1