pandoragami
pandoragami

Reputation: 5585

Build dll and link to it?

I'm on codeblocks 10.05 mingw on XP SP3 and I basically have the dll and the lib file built following the mingw site on creating a dll and linking to it. The problem I'm having is the second part where I'm trying to link to the library. I created a console application and used the following source:

#include <stdio.h>
#include "example_dll.h"

int main(void)
{
    hello("World");
    printf("%d\n", Double(333));
    CppFunc();

    MyClass a;
    a.func();

    return 0;
}

Then I setup my linker settings just like the site says by adding -L. -lexample_dll and I also link with the library file libexample_dll.a just like I would with many other libraries that have worked successfully with the same settings. Then when I try to link the executable I get an error,

 C:\example_dll_client\example_dll_client.cpp|2|error: example_dll.h: No such file or directory|
C:\example_dll_client\example_dll_client.cpp||In function 'int main()':|
C:\example_dll_client\example_dll_client.cpp|6|error: 'hello' was not declared in this scope|
C:\example_dll_client\example_dll_client.cpp|7|error: 'Double' was not declared in this scope|
C:\example_dll_client\example_dll_client.cpp|8|error: 'CppFunc' was not declared in this scope|
C:\example_dll_client\example_dll_client.cpp|10|error: 'MyClass' was not declared in this scope|
C:\example_dll_client\example_dll_client.cpp|10|error: expected ';' before 'a'|
C:\example_dll_client\example_dll_client.cpp|11|error: 'a' was not declared in this scope|
||=== Build finished: 7 errors, 0 warnings ===|

I also included the two files used for building the dll and lib files (not to the project but to this site for reference. I only have the source with the error as the entire project, otherwise what would the point of the dll be?).

//example_dll.cpp
#include <stdio.h>
#include "example_dll.h"

__stdcall void hello(const char *s)
{
        printf("Hello %s\n", s);
}
int Double(int x)
{
        return 2 * x;
}
void CppFunc(void)
{
        puts("CppFunc");
}
void MyClass::func(void)
{
        puts("MyClass.func()");
}
//example_dll.h
#ifndef EXAMPLE_DLL_H
#define EXAMPLE_DLL_H

#ifdef __cplusplus
extern "C" {
#endif

#ifdef BUILDING_EXAMPLE_DLL
#define EXAMPLE_DLL __declspec(dllexport)
#else
#define EXAMPLE_DLL __declspec(dllimport)
#endif

void __stdcall EXAMPLE_DLL hello(const char *s);

int EXAMPLE_DLL Double(int x);

#ifdef __cplusplus
}
#endif

// NOTE: this function is not declared extern "C"
void EXAMPLE_DLL CppFunc(void);

// NOTE: this class must not be declared extern "C"
class EXAMPLE_DLL MyClass
{
public:
        MyClass() {};
        virtual ~MyClass() {};
        void func(void);
};

#endif  // EXAMPLE_DLL_H

EDIT:

I made the following changes to the compilation of the DLL and lib file.

I first made sure that my build target is a dynamic library which can be found under the build targets tab by right clicking on the properties of the active project in the project manager tree. I also checked the create import library and the check .def exports file. I then went into the codeblocks build options and under the compiler settings->other-options tab I added

-c -shared

and under the #defines tab I added

BUILDING_EXAMPLE_DLL BUILD_DLL

My linker settings had user32 in the link libraries and under the linker settings I had -mwindows --out-implib

The build should now compile and link with no errors or warnings.

For compiling the source with the int main() I included the header file and also these settings:

Under the link libraries I had libexample_dll.dll.a and under the linker settings I had

-L. -lexample_dll

Upvotes: 2

Views: 4734

Answers (1)

moskito-x
moskito-x

Reputation: 11958

To me it looks like you have different directories for exe and dll.

So L. is not OK. Should be LpointsToThelibexample_dll.aFolder.

Either to copying example_dll.h in your exe directory or you use -IpointsToTheexample_dll.hFolder.

To be sure, due to incorrect command, the execution does not work.
I made a makefile.

To test the makefile

  • create a new directory.
  • copy example_dll.h , example_dll.cpp , example_dll.cpp files in there.
  • safe following code in the file makefile (in the same directory).

makefile

# Environment 
MKDIR=mkdir
CP=cp
CCADMIN=CCadmin


# build
builddll:
    g++ -c -DBUILDING_EXAMPLE_DLL example_dll.cpp
    g++ -shared -o example_dll.dll example_dll.o -Wl,--out-implib,libexample_dll.a

buildexe:
    g++ -c example_exe.cpp
    g++ -o example_exe.exe example_exe.o -L. -lexample_dll

clean:
    rm -f libexample_dll.a example_exe.exe example_dll.dll

Because of a copy and paste error.
Before you can use this makefile, replace all blank in front of the commands (g++ and rm) with two tabs.
Or you'll get an error like this. makefile:9: *** missing separator. Stop.

execute the following command.

  • make builddll
  • make buildexe

Now you can test example_exe.exe

only because of the completeness there is also a make clean.

  • make clean

UPDATE

If you want to use the DLL without headerfile, you have to know all the DLL functions.

Here's a loadDll.cpp that loads a DLL and calls Double.

/* 
 * File:   loadDll.cpp
 * Author: Administrator
 *
 * Created on 19. Februar 2013, 22:42
 */

#include <cstdlib>
#include <windows.h>
#include <stdio.h>

using namespace std;

typedef int (WINAPI *PFNDOUBLE)(int x);
PFNDOUBLE idlldouble;
HINSTANCE dllctrl_inst;

int main(int argc, char** argv) {
    puts("---start---");
    dllctrl_inst = LoadLibrary( "example_dll.dll" );
    if( dllctrl_inst != NULL ) {
      idlldouble = (PFNDOUBLE)GetProcAddress( dllctrl_inst, "Double" );
    }
    if( idlldouble != NULL ) {printf("%d\n", idlldouble(333));}
    return 0;
}

Upvotes: 3

Related Questions