Link to home
Start Free TrialLog in
Avatar of visualcortex
visualcortex

asked on

How to convert Exe Project to Lib

Hi all,
   I have a C project that is an EXE project which I need to convert into a lib (static or dynamic, static preferred) project. I have edited the .dsp file based on some info I saw off of the internet.

My problem is, when I compile the exe project, it obviously compiles and runs fine. When I try to compile it after converting it to the lib (static) type, I get a whole bunch of errors.

Attached are the DSP files for both projects.

Could someone PLEASE tell me what I am doing wrong?

Any help would be HIGHLY appreciated.

I am using MS Visual Studio 6.0
The original exe project
-----------------------------------------
# Microsoft Developer Studio Project File - Name="originalProject" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
 
# TARGTYPE "Win32 (x86) Application" 0x0101
 
CFG=originalProject - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE 
!MESSAGE NMAKE /f "originalProject.mak".
!MESSAGE 
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE 
!MESSAGE NMAKE /f "originalProject.mak" CFG="originalProject - Win32 Debug"
!MESSAGE 
!MESSAGE Possible choices for configuration are:
!MESSAGE 
!MESSAGE "originalProject - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "originalProject - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE 
 
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
 
!IF  "$(CFG)" == "originalProject - Win32 Release"
 
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\./" /I "..\..\..\charset/" /I "..\..\..\windows/" /I "..\..\..\unix/" /I "..\..\..\mac/" /I "..\..\..\macosx/" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\./" /I "..\..\..\charset/" /I "..\..\..\windows/" /I "..\..\..\unix/" /I "..\..\..\mac/" /I "..\..\..\macosx/" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 advapi32.lib comctl32.lib comdlg32.lib gdi32.lib imm32.lib shell32.lib user32.lib winmm.lib winspool.lib /nologo /subsystem:console /machine:I386
# SUBTRACT LINK32 /pdb:none
 
!ELSEIF  "$(CFG)" == "originalProject - Win32 Debug"
 
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\./" /I "..\..\..\charset/" /I "..\..\..\windows/" /I "..\..\..\unix/" /I "..\..\..\mac/" /I "..\..\..\macosx/" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\./" /I "..\..\..\charset/" /I "..\..\..\windows/" /I "..\..\..\unix/" /I "..\..\..\mac/" /I "..\..\..\macosx/" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 advapi32.lib comctl32.lib comdlg32.lib gdi32.lib imm32.lib shell32.lib user32.lib winmm.lib winspool.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# SUBTRACT LINK32 /pdb:none
 
!ENDIF 
 
# Begin Target
 
# Name "originalProject - Win32 Release"
# Name "originalProject - Win32 Debug"
# Begin Group "Source Files"
 
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
 
# End Group
# End Target
# End Project
 
---------------------------------------------------------------
 
 
Now, the modified file
 
 
---------------------------------------------------------------
 
# Microsoft Developer Studio Project File - Name="modifiedProject" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
 
# TARGTYPE "Win32 (x86) Static Library" 0x0104
 
CFG=modifiedProject - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE 
!MESSAGE NMAKE /f "modifiedProject.MAK".
!MESSAGE 
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE 
!MESSAGE NMAKE /f "modifiedProject.MAK" CFG="modifiedProject - Win32 Debug"
!MESSAGE 
!MESSAGE Possible choices for configuration are:
!MESSAGE 
!MESSAGE "modifiedProject - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "modifiedProject - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE 
 
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
 
!IF  "$(CFG)" == "modifiedProject - Win32 Release"
 
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
 
!ELSEIF  "$(CFG)" == "modifiedProject - Win32 Debug"
 
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\charset/" /I "..\..\..\windows/" /I "..\..\..\unix/" /I "..\..\..\mac/" /I "..\..\..\macosx/" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
 
!ENDIF 
 
# Begin Target
 
# Name "modifiedProject - Win32 Release"
# Name "modifiedProject - Win32 Debug"
# Begin Group "Source Files"
 
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
 
 
# End Group
# End Target
# End Project

Open in new window

Avatar of numberkruncher
numberkruncher
Flag of United Kingdom of Great Britain and Northern Ireland image

If it were me, I would run through the VC++ 6 wizard for creating a DLL of a similar specification to that of the EXE. Then I would piece the library together bit by bit (or at least as much as possible) whilst testing along the way. In the past I have found that it can be simpler to isolate issues along the way.

Additionally, I don't know if you are aware of this, in a DLL you must specify which symbols (i.e. functions, static variables, classes, etc.) are to be exported. Typically this can be achieved using #define statements.
// MYLIBRARY_EXPORTS should be added to your Library defines setting
// in your project build settings.
 
 
// Add this to a common header file which gets included at the top of each file.
// Put this at the top of your 'stdafx.h' if you have one. Remember to rename the
// macros accordingly, I've just used MYLIBRARY here.
#ifdef MYLIBRARY_EXPORTS
	#define MYLIBRARY_API __declspec(dllexport)
#else
	#define MYLIBRARY_API __declspec(dllimport)
#endif
 
 
// Then in your other headers you will need to explicitly export symbols.
 
MYLIBRARY_API int MyFunction(int value);
 
class MYLIBRARY_API MyClass
{
	// Inside the class, apart from static members, is the same as usual.
}
 
// Global instance of class.
extern MYLIBRARY_API MyClass GlobalInstance;

Open in new window

Avatar of visualcortex
visualcortex

ASKER

Thank you numberkruncher, for that information. I have however tried creating a new project on VC++ and manually adding these files to it with similar results. The errors are identical in both cases, which makes me wonder if somehow, this project was not designed to be made into a library. That probably is a wrong assumption on my part.

         I know these are just .C files and the only difference is that I did not add the export specification to the functions that I want to be visible for other projects that use this library, but I was trying to compile the raw source without any changes (it did afterall compile and run with no errors as an EXE project)
Would it be possible for you to post the errors that your getting?
numberkruncher, sorry for the delay in getting back to you. I looked at the post and actually got the compile time errors resolved, but when I put this library in my project folder, add it to the list of libraries to be included and compile, I get an unresolved external symbol error.

This is a C project that I have to make use of in a C++ project.

I have specified __declspec(dllexport) in a new header file that I created.

If this is out of the scope of the current issue, I apologize. I will open a new thread.
/*
 *	Header file for exporting the winplinkmain function 
 *	to outside functions. 
 *
 */
 
#ifdef __cplusplus
 
extern "C" {
 
#endif
/////////////////////////////////////////////////////////////////////////////
// Define the import/export tags
 
#define WPLINKIMPORT __declspec(dllimport)
#define WPLINKEXPORT __declspec(dllexport)
 
/////////////////////////////////////////////////////////////////////////////
 
WPLINKEXPORT int winplinkmain(int argc, char **argv);
 
#ifdef __cplusplus
}
 
#endif

Open in new window

I get the error in the main project. This library compiles fine.

I have done a

#include "winplink.h" in the cpp file of my project and call this function.
From my experience it is far simpler to make the compiler sort the imports/exports out automatically.
i.e.

#ifdef WPLINK_EXPORTS
#define WPLINK_API __declspec(dllexport)
#else
#define WPLINK_API __declspec(dllimport)
#endif

In your DLL you add the WPLINK_EXPORTS definition into your make file, and it automatically builds your library using exports. When it comes to using your library in your application file, WPLINK_EXPORTS is NOT defined in the project build settings, and thus the application gets built with dllimport version of the statements.

// In library this is: __declspec(dllexport) int foo(int bar);
// In application this is: __declspec(dllimport) int foo(int bar);
WPLINK_API int foo(int bar);

"unresolved external symbol error" usually refers to a missing library (.lib) include.

Make sure that you have "wplink.lib" (or whatever your library is called) in the imports section of your makefile, and make sure that Visual Studio is able to find that file (i.e. under additional paths).

Your DLL should have a file like the one shown in the source snippet below. You may already have this, I just noticed that you have a main function specified above, and thought that you may have missed it.
// MyLibrary.cpp
 
#include "Stdafx.h"
#include "MyLibrary.h"  // Your import/export macro should be in here
 
#include <windows.h>
 
// Note: This method is not explicitly exported with your macro.
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_PROCESS_DETACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
		break;
	}
    return TRUE;
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of numberkruncher
numberkruncher
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
thanks numberkruncher! I had already added my lib file in the project settings, but apparently VC was unable to find it. So I just gave the entire path and it compiled and ran fine!

Now my major cause of worry is when I build this project in the release mode rather than debug mode (which I have been doing currently), do I have to make any explicit changes apart from compiling my library in release mode and giving its explicit path?
Setting up release mode is pretty much the same as debug mode. Except double check that your linking the debug version of your library in your application debug mode, and the release version of your library in application release mode.
Thanks for explaining everything in a clear manner.
I am glad that I could be of help!