Manual OpenGL Extension Loading LNK2005 and LNK1169 - visual-studio

I'm using Visual C++ and manually attempting to load OpenGL extensions. However, for some reason defining the pointers from the Khronos Groups' provided headers leads to linker errors and as such I never get the change to even define these functions within my OpenGL context. Below I have included a simplified version of my code and it's structure that causes the same issue.
//Test.cpp
#include "MyGL.h"
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
//MyGL.h
#pragma once
#include "MyGLOpenGL.h"
//MyGL.cpp
#include "MyGL.h"
//MyGLOpenGL.h
#pragma once
#include <windows.h> // Windows functions
#include <GL/gl.h> // Provided w/ Compiler
#include "GL/glext.h" // Put out by Khronos Group
#include "GL/wglext.h" // Put out by Khronos Group
#pragma comment(lib, "opengl32.lib") // Provided w/ Compiler
#ifndef GL_OPENGL
#define GL_OPENGL
void glInitPointers(); // Defines pointers to opengl functions
void* glGetAnyProcAddress(const char* name); // Gets a pointer to any OpenGL function
extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
#endif
//MyGLOpenGL.cpp
#include "MyGLOpenGL.h"
void glInitPointers() {
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)glGetAnyProcAddress("wglChoosePixelFormatARB"); //load function
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)glGetAnyProcAddress("wglCreateContextAttribsARB"); //load function
return;
}
void* glGetAnyProcAddress(const char* name) {
void *pointer = (void *)wglGetProcAddress(name);
if (pointer == 0 || (pointer == (void*)0x1) || (pointer == (void*)0x2) || (pointer == (void*)0x3) || (pointer == (void*)-1)) {
HMODULE module = LoadLibraryW(L"opengl32.dll");
pointer = (void *)GetProcAddress(module, name);
}
return pointer;
};
Compiling this gives me the following linker errors:
1>MyGLOpenGL.obj : error LNK2001: unresolved external symbol "int (__stdcall* wglChoosePixelFormatARB)(struct HDC__ *,int const *,float const *,unsigned int,int *,unsigned int *)" (?wglChoosePixelFormatARB##3P6GHPAUHDC__##PBHPBMIPAHPAI#ZA)
1>MyGLOpenGL.obj : error LNK2001: unresolved external symbol "struct HGLRC__ * (__stdcall* wglCreateContextAttribsARB)(struct HDC__ *,struct HGLRC__ *,int const *)" (?wglCreateContextAttribsARB##3P6GPAUHGLRC__##PAUHDC__##PAU1#PBH#ZA)
1>G:\Development\Test\Debug\Test.exe : fatal error LNK1120: 2 unresolved externals
As the issue was unresolved external symbols, I tried removing the extern keyword to arrive at getting these two errors instead:
1>MyGLOpenGL.obj :error LNK2005: "int (__stdcall* wglChoosePixelFormatARB)(struct HDC__ *,int const *,float const *,unsigned int,int *,unsigned int *)" (?wglChoosePixelFormatARB##3P6GHPAUHDC__##PBHPBMIPAHPAI#ZA) already defined in MyGL.obj
1>MyGLOpenGL.obj : error LNK2005: "struct HGLRC__ * (__stdcall* wglCreateContextAttribsARB)(struct HDC__ *,struct HGLRC__ *,int const *)" (?wglCreateContextAttribsARB##3P6GPAUHGLRC__##PAUHDC__##PAU1#PBH#ZA) already defined in MyGL.obj
1>Test.obj : error LNK2005: "int (__stdcall* wglChoosePixelFormatARB)(struct HDC__ *,int const *,float const *,unsigned int,int *,unsigned int *)" (?wglChoosePixelFormatARB##3P6GHPAUHDC__##PBHPBMIPAHPAI#ZA) already defined in MyGL.obj
1>Test.obj : error LNK2005: "struct HGLRC__ * (__stdcall* wglCreateContextAttribsARB)(struct HDC__ *,struct HGLRC__ *,int const *)" (?wglCreateContextAttribsARB##3P6GPAUHGLRC__##PAUHDC__##PAU1#PBH#ZA) already defined in MyGL.obj
1>G:\Development\Test\Debug\Test.exe : fatal error LNK1169: one or more multiply defined symbols found
I've also already made sure that "#pragma once" was in ever file, header guards, adding "OpenGL32.lib" into the additional dependencies in visual studio, adding a pragma comment for the lib, setting the pointers equal to null in the declaration, and I'm just at a complete loss for anything else to try, even after googling the issue. And in my case, using GLEW or any other extension loading library because that is exactly what I'm trying to create.

In C and C++ there's an important difference between declaration and definition. A statement of the form
extern <type> <symbol>;
declares that there is some symbol somewhere, but it doesn't actually bring it into existence. It's more like a promise to the compiler, that the symbol will be defined somewhere else. When you wrote
extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
you actually didn't create the variables for those function pointers, you just "listed them in the table of contents" for your program. You actually have to define them somewhere. I.e. in some compilation unit you have to write (without the extern).
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
This has absolutely nothing to do with initialization, as hinted by #EricLopushansky; it's all about them being getting actually defined. Since these are global scope, they'll be initialized to 0 anyway, even if you don't explicitly write that = 0.

This isn't very well explained by the OpenGL wiki in the article Load OpenGL Functions but simply do the following. Setting the pointer to null within the cpp file will fix the issue.
For example:
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
For anyone interested, here is the relevant code from GLEW that serves the same purpose:
//glew.h
#ifdef GLEW_STATIC
# define GLEWAPI extern
#else
# ifdef GLEW_BUILD
# define GLEWAPI extern __declspec(dllexport)
# else
# define GLEWAPI extern __declspec(dllimport)
# endif
#endif
#define GLEW_FUN_EXPORT GLEWAPI
//wglew.h
#define WGLEW_GET_FUN(x) x
#define wglChoosePixelFormatARB WGLEW_GET_FUN(__wglewChoosePixelFormatARB)
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
#define WGLEW_FUN_EXPORT GLEW_FUN_EXPORT
WGLEW_FUN_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB;
//glew.c
# define glewGetProcAddress(name) wglGetProcAddress((LPCSTR)name)
PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB = NULL;
r = ((wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)glewGetProcAddress((const GLubyte*)"wglChoosePixelFormatARB")) == NULL) || r;
//I would be using this static so it would evaluate in my code to
//MyGLOpenGL.h
#define wglChoosePixelFormatARB __wglewChoosePixelFormatARB
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
extern PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB;
//MyGLOpenGL.cpp
PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB = NULL;
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress((const GLubyte*)"wglChoosePixelFormatARB")

Related

How to use NtOpenProcess

I am trying to use NtOpenProcess() I have not find any example in town.
I am getting an error any help is much appreciated.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR szCmdLine, int showCmd)
{
HANDLE handle;
HWND myWindow =FindWindow(NULL, L"Notepad");
PCLIENT_ID PID;
GetWindowThreadProcessId(myWindow, (LPDWORD)&PID);
ZwOpenProcess(&handle, PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, NULL,PID);
return 0;
}
The errors are
1>c:\users\asus\source\repos\windowsproject2\windowsproject2\windowsproject2.cpp(14): error C2065: 'PCLIENT_ID': undeclared identifier
1>c:\users\asus\source\repos\windowsproject2\windowsproject2\windowsproject2.cpp(14): error C2146: syntax error: missing ')' before identifier 'PID'
1>c:\users\asus\source\repos\windowsproject2\windowsproject2\windowsproject2.cpp(14): error C3861: 'NtOpenProcess': identifier not found
1>c:\users\asus\source\repos\windowsproject2\windowsproject2\windowsproject2.cpp(14): error C2146: syntax error: missing ';' before identifier 'PID'
1>c:\users\asus\source\repos\windowsproject2\windowsproject2\windowsproject2.cpp(14): error C2059: syntax error: ')'
This are my include files.
#include <Windows.h>
#include <ntddk.h>
#include <Ntifs.h>
#include "stdafx.h"
at first look at code:
FindWindow(NULL, L"Notepad");
faster of all you want
FindWindow(L"Notepad", 0);
because L"Notepad" is class name (not window name) and class name first parameter.
PCLIENT_ID PID;
GetWindowThreadProcessId(myWindow, (LPDWORD)&PID);
the GetWindowThreadProcessId wait pointer to DWORD memory, where it store process id. but you pass to it uninitialized pointer, to random memory. need use this:
CLIENT_ID pid = { };
if (GetWindowThreadProcessId(myWindow, (PDWORD)&pid.UniqueProcess))
finally ObjectAttributes in call NtOpenProcess is mandatory parameter and can not be 0.
about undeclared identifiers - all this declared in ntifs.h and it sub-headers (ntifs.h include ntddk.k - so you not need include it direct). problem that windows.h and ntifs.h is conflict - many common declarations. if you include both - you got a lot of errors. but solution exist - include ntifs.h in some namespace. but even after this you got some errors. but this also can be fixed, if deep understand source of errors. also you will be need include own code to this namespace too, for have easy access to ntifs declarations. and finally you need use ntdll.lib or ntdllp.lib (will be conflict with CRT libs if you use it) as linker input.
so if you want use native api in own code, without add custom headers, where you copy-paste some nt definitions and call it without resolve api in runtime, but use static linking - this is possible, but require deep knowledge and understanding what you doing. example
#define DECLSPEC_DEPRECATED_DDK
#define _XX_BEGIN namespace XX {
#define _XX_END }
_XX_BEGIN
struct _SECURITY_QUALITY_OF_SERVICE;
struct _CONTEXT;
_XX_END
#define _INC_MMSYSTEM /* Prevent inclusion of mmsystem.h in windows.h */
#include <windows.h>
#pragma warning(disable : 4005)
_XX_BEGIN
#ifdef _RTL_RUN_ONCE_DEF
#undef _RTL_RUN_ONCE_DEF
#endif
#define RtlCompareMemory ::RtlCompareMemory
#include <ntifs.h>
_XX_END
#undef _INC_MMSYSTEM /* Prevent inclusion of mmsystem.h in windows.h */
#include <MMSystem.h>
_XX_BEGIN
void demo()
{
if (HWND myWindow = FindWindow(L"Notepad", 0))
{
CLIENT_ID pid = { };
if (GetWindowThreadProcessId(myWindow, (PDWORD)&pid.UniqueProcess))
{
HANDLE handle;
static OBJECT_ATTRIBUTES zoa = { sizeof(zoa) };
if (0 <= NtOpenProcess(&handle,
PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
&zoa, &pid))
{
NtClose(handle);
}
}
}
}
_XX_END

#including <alsa/asoundlib.h> and <sys/time.h> results in multiple definition conflict

Here is the minimal C program to reproduce:
#include <alsa/asoundlib.h>
#include <sys/time.h>
int main( void )
{
}
This will compile with gcc -c -o timealsa.o timealsa.c, but if you include the -std=c99 switch, you get a redefinition error:
In file included from /usr/include/sys/time.h:28:0,
from timealsa.c:3:
/usr/include/bits/time.h:30:8: error: redefinition of ‘struct timeval’
struct timeval
^
In file included from /usr/include/alsa/asoundlib.h:49:0,
from timealsa.c:2:
/usr/include/alsa/global.h:138:8: note: originally defined here
struct timeval {
^
How can I resolve this conflict while still using -std=c99?
Since your question suggests you are using GLIBC's time.h there is a way to avoid this by telling it not to define timeval. Include asoundlib.h first then define _STRUCT_TIMEVAL. The one defined in asoundlib.h will be the one that gets used.
#include <alsa/asoundlib.h>
#ifndef _STRUCT_TIMEVAL
# define _STRUCT_TIMEVAL
#endif
#include <sys/time.h>
int main( void )
{
}
With C99 and later you can't have duplicate definitions of the same struct. The problem is that alsa/asoundlib.h includes alsa/global.h which contains this code:
/* for timeval and timespec */
#include <time.h>
...
#ifdef __GLIBC__
#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE)
struct timeval {
time_t tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#endif
#endif
So the Michael Petch's solution won't work - by the time you've included alsa/asoundlib.h it is already too late. The proper solution is to define _POSIX_C_SOURCE (_POSIX_SOURCE is obsolete). There's more information about these macros here and here.
For example you could try -D_POSIX_C_SOURCE=200809L. However, if you do that you'll get errors like this:
/usr/include/arm-linux-gnueabihf/sys/time.h:110:20: error: field ‘it_interval’ has incomplete type
struct timeval it_interval;
^
/usr/include/arm-linux-gnueabihf/sys/time.h:112:20: error: field ‘it_value’ has incomplete type
struct timeval it_value;
^
/usr/include/arm-linux-gnueabihf/sys/time.h:138:61: error: array type has incomplete element type
extern int utimes (const char *__file, const struct timeval __tvp[2])
^
This is all a big mess of old C code and macro madness. The only way I got it to work was to give up and use -std=gnu11.

vs 2010: error LNK2028: unresolved token (0A000342) "extern "C" int __stdcall

The following code is taken from here. I removed all Windows NT part as I am working on Windows 7.
I copied this code and run in visual studio 2010 (New project-> VC++->CLR->CLR Console... ). But it is giving lots of unresolved extern 'c' errors as listed below the code. What wrong I have committed?
#define STRICT 1
#include <windows.h>
#include <iostream>
using namespace std;
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
DWORD dwThreadId, dwProcessId;
HINSTANCE hInstance;
char String[255];
HANDLE hProcess;
if (!hWnd)
return TRUE; // Not a window
if (!::IsWindowVisible(hWnd))
return TRUE; // Not visible
if (!SendMessage(hWnd, WM_GETTEXT, sizeof(String), (LPARAM)String))
return TRUE; // No window title
hInstance = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE);
dwThreadId = GetWindowThreadProcessId(hWnd, &dwProcessId);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
cout << hWnd << ' ' << dwProcessId << '\t' << String << '\t';
cout << "(None)\n";
CloseHandle(hProcess);
return TRUE;
}
int main(int argc, char *argv[], char *envp[]) {
EnumWindows(EnumWindowsProc, NULL);
return 0;
}
This is giving following Errors(and other similar unresolved extern C errors)
1>wndowfind.obj : error LNK2028: unresolved token (0A000342) "extern "C" int __stdcall
EnumWindows(int (__stdcall*)(struct HWND__ *,long),long)" 3
(?EnumWindows##$$J18YGHP6GHPAUHWND__##J#ZJ#Z) referenced in function "int __cdecl
main(int,char * * const,char * * const)" (?main##$$HYAHHQAPAD0#Z)
1>wndowfind.obj : error LNK2028: unresolved token (0A000346) "extern "C" unsigned long
__stdcall GetWindowThreadProcessId(struct HWND__ *,unsigned long *)"
(?GetWindowThreadProcessId##$$J18YGKPAUHWND__##PAK#Z) referenced in function "int __stdcall
EnumWindowsProc(struct HWND__ *,long)" (?EnumWindowsProc##$$FYGHPAUHWND__##J#Z)
1>wndowfind.obj : error LNK2028: unresolved token (0A000347) "extern "C" long __stdcall
GetWindowLongW(struct HWND__ *,int)" (?GetWindowLongW##$$J18YGJPAUHWND__##H#Z) referenced in
function "int __stdcall EnumWindowsProc(struct HWND__ *,long)"
(?EnumWindowsProc##$$FYGHPAUHWND__##J#Z)
1>wndowfind.obj : error LNK2019: unresolved external symbol "extern "C" int __stdcall
EnumWindows(int (__stdcall*)(struct HWND__ *,long),long)"
(?EnumWindows##$$J18YGHP6GHPAUHWND__##J#ZJ#Z) referenced in function "int __cdecl
main(int,char * * const,char * * const)" (?main##$$HYAHHQAPAD0#Z)
1>c:\users\afnan\documents\visual studio 2010\Projects\wndowfind\Debug\wndowfind.exe : fatal
error LNK1120: 10 unresolved externals
1>
1>Build FAILED.
UPDATED
By including the libraries (as suggested in the answers), I was able to run the program successfully. But I am not able to understand why only first character of string is printing not the complete one, as can be seen in the output:
00010060 2652 S (None)
002502B2 5820 C (None)
00090402 5160 w (None)
00050392 5160 w (None)
00060292 3520 F (None)
000C02BA 3520 M (None)
0001021A 3736 E (None)
00040018 896 I (None)
00010170 3580 A (None)
0002003E 2684 D (None)
00030316 4956 N (None)
000202DE 3736 D (None)
0001031E 2652 S (None)
000100EA 2652 P (None)
In the output above, S is actually "start", C is "console" etc I confirmed through spy++ tool.
How can I print the complete string instead of just first character?
CLR projects by default do not include the standard Windows libraries, such as user32.lib.
Edit your project properties, find the Linker Inputs option, and add kernel32.lib user32.lib advapi32.lib which are the usual libraries needed by Win32 code.

Symbols Missing for nsiCookieManager2 program

Please help me with the missing LIBs for this MOZILLA program.
Trying to create cookie using nsICookieManager2
I have tried with all the existing libs in Mozilla SDK
Regards
C:\Code>cl.exe FFCookie.cpp /I "C:\xulrunner-sdk\include" mozalloc.lib xpcomglue.lib /link /LIBPATH:"C:\xulrunner-sdk\lib"
Symbols Missing:
FFCookie.obj : error LNK2019: unresolved external symbol "public: void
__thiscall nsCOMPtr_base::assign_from_gs_contractid_with_er ror(class nsGetServiceByContractIDWithError const &,struct nsID const &)"
(?assign_from_gs_contractid_with_error#nsCOMPtr_base##QA
EXABVnsGetServiceByContractIDWithError##ABUnsID###Z) referenced in
function "public: __thiscall nsCOMPtr::
nsCOMPtr(class
nsGetServiceByContractIDWithError const &)"
(??0?$nsCOMPtr#VnsICookieManager####QAE#ABVnsGe
tServiceByContractIDWithError###Z)
FFCookie.obj : error LNK2019: unresolved external symbol "public: void
__thiscall nsCOMPtr_base::assign_from_qi(class nsQueryInter face,struct nsID const &)"
(?assign_from_qi#nsCOMPtr_base##QAEXVnsQueryInterface##ABUnsID###Z)
referenced in function "public: __t hiscall nsCOMPtr::nsCOMPtr(class
nsQueryInterface)" (??0?$nsCOMPtr#VnsICookieMan
ager2####QAE#VnsQueryInterface###Z) FFCookie.exe : fatal error
LNK1120: 2 unresolved externals
#include "nsICookieManager.h"
#include "nsICookieManager2.h"
#include "nsServiceManagerUtils.h"
#include "nsComPtr.h"
#include "nsNetCID.h"
#include "nsStringAPI.h"
#include "mozilla-config.h"
int main()
{
nsresult rv;
nsCOMPtr<nsICookieManager> cookieManager = do_GetService (NS_COOKIEMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
if (cookieManager)
{
nsCOMPtr<nsICookieManager2> cookieManager2 = do_QueryInterface(cookieManager);
if (cookieManager2)
{
cookieManager2->Add(NS_LITERAL_CSTRING("ud.abc.com"),
NS_LITERAL_CSTRING("//"),
NS_LITERAL_CSTRING("TK"),
NS_LITERAL_CSTRING("abc"), 0x1, 0x1, 0, -1);
}
}
return 0;
}
Questions:
I dont find any info with function documentation regarding which LIB to include (as I find on MSDN)
Any clue on how to figure out LIB corresponding to particular function for MOZILLA.
The problem isn't with the lib, the symbol missing is defined in the xpcomglue library. However, you seem to have some compile parameters that don't match the parameters used to compile XULRunner/Firefox. The symbols your compiler is looking for contain "QAEX" as parameter description whereas the library defines them with "QAIX". Looking at the name mangling table, your compiler expects unsigned char where Mozilla has unsigned int. I suspect that the reason is you compiling your application without Unicode support - change main() into wmain()?

Visual Studio, MSBuild: First build after a clean fails, following builds succeed

There's obviously something wrong with my build, but I can't figure it out. I narrowed this down to one of my projects: first build after clean fails, all following builds succeed.
I get linking errors which say that some symbols are already defined:
>------ Build started: Project: Problem, Configuration: Debug Win32 ------
> Blah blah blah...
23> Creating library D:\SVN.DRA.WorkingCopy\Debug\Problem.lib and object D:\SVN.DRA.WorkingCopy\Debug\Problem.exp
23>ProblemDependency1.lib(PD1.obj) : error LNK2005: "public: unsigned short __thiscall PD2Class::getFoo(void)const " (?getFoo#PD2Class##QBEGXZ) already defined in ProblemDependecy2.lib(ProblemDependency2.dll)
23>ProblemDependency1.lib(PD1.obj) : error LNK2005: "public: void __thiscall PD2Class2::`default constructor closure'(void)" (??_FPD2Class2#Image#DRA##QAEXXZ) already defined in ProblemDependency2.lib(ProblemDependency2.dll)
23>D:\SVN.DRA.WorkingCopy\Debug\Problem.dll : fatal error LNK1169: one or more multiply defined symbols found
Problem is a C++/CLI project, built with the /clr switch, which references the unmanaged C++ projects ProblemDependency1, a static lib, and ProblemDependency2, a dll.
ProblemDependency1 references ProblemDependency2.
getFoo() is declared as inline and defined outside of the class declaration, in the .h
PD2Class2 doesn't have an explicitly defined default constructor, but it has a constructor which has all default arguments, so you could say it includes the default constructor as a special case
The .h's where these are defined have #pragma once as their first line.
Any hint on troubleshooting this? I can post more info if needed
Update: I solved the first error thanks to Anders Abel's suggestion, but I still can't solve the second one (the one about the default constructor)
Update: If I compile using MSBuild outside Visual Studio, it fails always, with the same error
Edit: Here's some code. First, a bit of PD2Class2's declaration. PD2Class2's real name is CImage (feeling lazy to anonymize), CImage.h:
#pragma once
#pragma warning( disable: 4251 ) //TODO: Disable and solve
#include "ImageProperties.h"
#include "../CommonCppLibrary/CriticalSection.h"
#include <windows.h>
#include <stdexcept>
#include <string>
class CSharedMemory;
class EmptyImageException;
struct IShape;
struct SImageStatics {
unsigned short low3Percentile;
unsigned short high97Percentile;
unsigned short medianPixelValue;
unsigned short meanPixelValue;
unsigned short minPixelValue;
unsigned short maxPixelValue;
};
namespace DRA{
namespace Image{
class __declspec(dllexport) CImage {
friend class CImageLock;
//Attributes
int m_iPitch;
protected:
mutable CImageProperties m_cProperties;
CSharedMemory * m_pSharedMemmory;
mutable DRA::CommonCpp::CCriticalSection m_csData;
static const float PIXEL_FREQUENCY_COVERAGE;
static const float PIXEL_CUTOFF_PERCENTAGE;
static const int MINIMUM_PIXEL_FREQUENCY; //Pixels with a frequency lower than this are ignored
static const int MINIMUM_WINDOW_WIDTH_FOR_16_BITS;
//Methods
//Some private methods
public:
CImage( DWORD dwWidth = 0, DWORD dwHeight = 0, ULONG uBytesPerPixel = 0,
bool isSigned = false, EPhotometricInterpretation ePI = PI_UNKNOWN,
UINT bitsStored = 0, float pw = -1.0f, float ph = -1.0f, BYTE * pData = NULL );
CImage( const CImageProperties& cProperties, int iPitch = 0 );
CImage( const CImage& rImage );
virtual ~CImage();
virtual CImage& operator=( const CImage& );
bool operator==( const CImage& rImage );
//Alter State
//More methods
//Query State
//More methods
};
}
}
Next, the constructor's definition, from CImage.cpp:
CImage::CImage( DWORD dwWidth, DWORD dwHeight, ULONG uBytesPerPixel, bool isSigned,
EPhotometricInterpretation ePI, UINT bitsStored, float pw, float ph,
BYTE * pData ) :
m_iPitch( dwWidth * uBytesPerPixel ),
m_cProperties( dwWidth, dwHeight, uBytesPerPixel, bitsStored, ePI, isSigned, pw, ph ),
m_pSharedMemmory( NULL ),
m_csData(){
m_pSharedMemmory = new CSharedMemory( pData ? pData : new BYTE[getSize()] );
}
Is getFoo() marked as __declspec(dllexport)? If it is an inline function, it is instantiated/used from wherever it is called through the included header. It shouldn't be part of the functions that the dll exports and it should not have a dllexport directive.
__declspec(dllexport) might be handled through a macro that is expanded to dllexport or dllimport depending on if it is the dll or code using the dll that is compiled. If there is any macro in the function declaration you might have to dig into it to find if there is an export directive.
Update
I think that if the header file is used both when the dll is built and when the dll is used, it is incorrect to have __declspec(dllexport) in the header file. Instead use a macro system:
#ifdef PROBLEMDEPENDENCY2
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
class DLLEXPORT CImage
{
//...
}
Then define the PROBLEMDEPENDENCY2 preprocessor symbol when building the dll, but not when using it. The problem with hardcoding __declspec(dllexport) in the header file is that the compiler will try to export the class both from ProblemDependency2 (which is correct) and from ProblemDependency1 (which is incorrect).
Just something I've run into recently to check:
Are you building on a network volume? I had been having problems with not being able to debug my applications because the .pdb file was not "there" after the build and before the debug launch due to latency in the SAN that I was working on as a build directory.
Once I moved the project build to a local volume, everything was fine.
Don't know if that's what's happening to you or not, but something I'd look into.
I dont' have much c++ experience, but problems like this in other .NET languages, often result from having a DLL reference to another project in the same solution (to the DLL in the "obj" or "bin" folder of the other project, instead of a project reference. This stops Visual Studio from being able to figure out the build order, and, hence, the first time after a "clean", you will not have the DLL you are depending on. On the second build, this DLL will already have been built, and the build will succeed.

Resources