How to Make Project DLLs Reference each other in a Workspace

General questions regarding the usage of CodeLite
User avatar
ColleenKobe
CodeLite Expert
Posts: 130
Joined: Wed Mar 30, 2016 4:31 pm
Genuine User: Yes
IDE Question: C++
Contact:

How to Make Project DLLs Reference each other in a Workspace

Post by ColleenKobe »

I am translating six Visual Basic projects into C and C++ in CodeLite. In CodeLite, I made one workspace with six projects in it. I set up five of the projects to compile to a dll, and the last one to an executable. The last project is the main program, and is a C++ GUI using wxCrafter.

My problem is that I can build a dll from the first project, but I can't get any of the other projects to reference the first dll during the linking process. The linking of the other projects all error out.

To make it easier to describe this problem, I'll call my projects:

Project_A (contains global procedures and identifiers)
Project_B
Project_C
Project_D
Project_E
Project_Z (main program)

Project_A contains global procedures and identifiers. It is compiling into a dll very nicely, and the dll is getting put in the directory that I specified.

The next thing I want to do is compile Project_B. Project_B calls global utilities in Project_A.

I found that if I add the source code for the global procedures and identifiers to Project_B, then Project_B.dll builds just fine. But it seems wasteful to have the same code repeated in every project. It would be better to just have that code in Project A, and the other projects reference it.

I tried building Project_B WITH the *.h files from Project_A, but WITHOUT the *.c files from Project_A, and adding the path to the directory where the dlls reside, as needed. In the Project_B Settings/Global Settings/Libraries, I also added Project_A as a library. But when I link Project B, I get "undefined reference to 'x'" errors for the identifiers in Project_A.

What do I need to do to make Project_B know it can find the utilities and global identifiers in Project_A.dll?

Thank you!

Colleen
User avatar
eranif
CodeLite Plugin
Posts: 6373
Joined: Wed Feb 06, 2008 9:29 pm
Genuine User: Yes
IDE Question: C++
Contact:

Re: How to Make Project DLLs Reference each other in a Works

Post by eranif »

Its a C++ question...

Usually you would simply include a header file from the DLL project to other projects by adding a simple #include statement in your code.
For link, you will need to add the path for the DLL and the DLL name in Project settings->linker page

Note that on Windows, you will probably need to declare your classes with the declspec keyword (Windows only)
https://msdn.microsoft.com/en-us/library/a90k134d.aspx

Eran
Make sure you have read the HOW TO POST thread
User avatar
ColleenKobe
CodeLite Expert
Posts: 130
Joined: Wed Mar 30, 2016 4:31 pm
Genuine User: Yes
IDE Question: C++
Contact:

Re: How to Make Project DLLs Reference each other in a Works

Post by ColleenKobe »

Thank you for the suggestions, eranif.

Actually, even before you answered, I did (and still do) have an #include statement for the header files declaring the values that give me error messages ("undefined reference to 'x'). I do declare __declspec. I do have paths declared in "Global Settings" for all projects, showing where the library and files reside, and I am sure the files are IN there. I have set up my main program with the sequence of how to compile the projects: the utility dll that everyone depends on first, then the other projects, with the main program last. So I have already tried everything you have suggested, and I still can't get gcc to find my global variables.

I'm sorry. I know you could not have known any of this because I did not post any code. I did not post code because I didn't want to overwhelm you with too much information.

Here is more information about my workspace. Note: here are the real names of my projects, and what they reference.

Code: Select all

Project Name            Description
------------            ---------------------------------
dfvint                  References utilitiesandglobaldata.
dfvproc                 References utilitiesandglobaldata.
dfvset                  References utilitiesandglobaldata.
main                    Main program.  References utilitiesandglobaldata, dfvint, dfvproc, and dfvset.
utilitiesandglobaldata  Utilities and global data. Does not reference any other project.
"utilitiesandglobaldata" compiles and builds just fine.

I'll give you all the info I think might be helpful for ONE project, dfvint, as an example.
For starters, here is the source code.

H File

Code: Select all

#ifndef DFVINT_H
#define DFVINT_H

#include <windef.h>                     // This command must appear BEFORE the
// following commands (if applicable):
//   #include winnt.h
//   #define CALL_TYPE __stdcall

// Make sure functions are exported with C linkage under C++ compilers.
#ifdef __cplusplus
extern "C"
{               // Export the following code with C linkage.
#endif          // Notice that this block is still open. It is closed below.

#define DllExport  __declspec(dllexport)
#define DllImport  __declspec(dllimport)
#define CALL_TYPE  __stdcall

#ifndef UNICODE
#define UNICODE
#endif

#include <winbase.h>

#include "gmem.h"
#include "ut.h"

// =============================================================================
//                               Global Variables
// =============================================================================
extern  Int8    dfvint_X;
extern  UInt16  dfvint_Y;
extern  WORD    dfvint_Z;

// =============================================================================
// dfvint_Read_Loop is run from within a thread, which is why its
// declaration is different from the other procedures and functions.

extern              DWORD       WINAPI      dfvint_Thread       (void);  // our Thread. :-D

extern  DllExport   long        CALL_TYPE   dfvint_Initialize   (void);
extern  DllExport   long        CALL_TYPE   dfvint_Terminate    (void);

//====================

#ifdef __cplusplus
}               // Export the following code with C linkage.
#endif

#endif // DFVINT_H
C File

Code: Select all

#include <windef.h>                     // This command must appear BEFORE the
                                        // following commands (if applicable):
                                        //   #include winnt.h
                                        //   #define CALL_TYPE __stdcall

// Make sure functions are exported with C linkage under C++ compilers.
#ifdef __cplusplus
extern "C"
{               // Export the following code with C linkage.
#endif          // Notice that this block is still open. It is closed below.

#define DllExport  __declspec(dllexport)
#define DllImport  __declspec(dllimport)
#define CALL_TYPE __stdcall

#ifndef UNICODE
#define UNICODE
#endif

#include "printmsgs.h"                  // Compiler debug print statement controller.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>                     // Only including stdarg.h to cover
                                        // definition of va_list in winbase.h.
#include <winbase.h>

#include "gmem.h"
#include "ut.h"
#include "utilitiesandglobaldata.h"
#include "dfvint.h"

// =============================================================================
//        Global Variable Declarations.  Defined as "extern" in dfvint.h.
// =============================================================================
Int8    dfvint_X;
UInt16  dfvint_Y;
WORD    dfvint_Z;

// *****************************************************************************
DWORD       WINAPI      dfvint_Thread             (void)  // our Thread. :-D
{  // dfvint_Thread_Proc
    return (1);     // for now.
} // dfvint_Thread_Proc

// *****************************************************************************
DllExport long CALL_TYPE dfvint_Initialize (void)
{
    long    rc  = TRUE;
    // -------------------------------------------------------------------------
    ut_Entering (g_STDOUT, "dfvint_Initialize");
    ut_Display_Always (g_STDOUT, "    dfvint_Initialize: Well, here we are.  Now what?");
    dfvint_X    = -8;
    dfvint_Y    = 16;
    dfvint_Z    = 0xFF;
    ut_Exiting  (g_STDOUT, "dfvint_Initialize");
    return (rc);
} // dfvint_Initialize


// *****************************************************************************
DllExport long CALL_TYPE dfvint_Terminate (void)
{
    long    rc  = TRUE;
    // -------------------------------------------------------------------------
    ut_Entering (g_STDOUT, "dfvint_Terminate");
    ut_Display_Always (g_STDOUT, "    dfvint_Terminate: Well, here we are.  Now what?");
    ut_Exiting  (g_STDOUT, "dfvint_Terminate");
    return (rc);
} // dfvint_Terminate

// -----------------------------------------------------------------------------

#ifdef __cplusplus
}               // Export the preceding code with C linkage.
#endif

Here is a screen shot for the dfvint Project Properties:
Kobe--dfvintProjectSettings.jpg
Here is a screen shot showing the build order for main:
Kobe--BuildOrder.jpg
And last, here is the result of "Build Workspace". The resulting file is more than 10K lines long, mostly due to compiler warnings about deprecated function calls. I would sure love to know how to get rid of those messages, without losing other more important messages!
Note: the only dll that this build produced was a utilitiesandglobaldata.dll.
Kobe--BuildResults.txt
I am still stuck. I have tried a lot of different approaches to make the projects dependent on a utility dll to actually link correctly to the utility dll. Nothing I tried worked. I can write up a list of everything I've tried, but that will make my next posting lengthy.

To summarize:

1. The projects referencing the utility project, never find the utility project information that they need.
2. The projects are not compiling in the "Build Order" sequence that I specified for the main program. I did not submit values for the "Build Order" for the other projects. Should I have?

Is there a way to add a "resource" to my utility project? I am using CodeLite 9.2.0 and I don't see where to add a resource. I am going to try adding my utility dll to the project resources. Maybe then, gcc will find the missing declarations.

------------------
Software Versions:
------------------
CodeLite: 9.2.0 Downloaded from web site.
gcc: 4.9.3
tdm-gcc: 5.1.0.3
Windows 7: 6.1
wxCrafter: 2.5
wxWidgets: 3.1.0

Target build: debug
Target platform: 32-bit
You do not have the required permissions to view the files attached to this post.
User avatar
eranif
CodeLite Plugin
Posts: 6373
Joined: Wed Feb 06, 2008 9:29 pm
Genuine User: Yes
IDE Question: C++
Contact:

Re: How to Make Project DLLs Reference each other in a Works

Post by eranif »

g_STDOUT is used in the "C" file, but it not defined anywhere ... (at least in the H file you pasted here, nor in the "C" file)

Eran
Make sure you have read the HOW TO POST thread
User avatar
ColleenKobe
CodeLite Expert
Posts: 130
Joined: Wed Mar 30, 2016 4:31 pm
Genuine User: Yes
IDE Question: C++
Contact:

Re: How to Make Project DLLs Reference each other in a Works

Post by ColleenKobe »

You are correct, Eranif. g_STDOUT is a variable declared in utilitiesandglobaldata.dll. utilitiesandglobaldata is the dll I am trying to reference when I build project dfvint.

g_STDOUT is declared in gmem.h as "extern". I do include gmem.h in project dfvint. But I do not include gmem.c in project dfvint, because then I wouldn't be including gmem data as a dll.

Other things declared utilitiesandglobaldata.dll are procedures ut_Entering and ut_Exiting.

Curiously, I don't get error messages for ut_Entering and ut_Exiting.

Running Dependency Walker (http://www.dependencywalker.com/) on utilitiesandglobaldata.dll, I do see ut_Entering and ut_Exiting appear correctly in the dll. But I don't see g_STDOUT. Then again, I don't think Dependency Walker displays variables. Just procedures and functions.

Could it be that the linker can't set up code to directly reference variables stored in a dll? That I can only get variables in a dll via function and procedure calls? Like making a "Set_g_STDOUT" and "Get_g_STDOUT" (which do not currently exist)?

Colleen
Post Reply