Unresolved externals and extern "C"? - c++

As new as I am to C++, I don´t fully understand this linking and stuff.
And I think this is about extern "C" linking.
extern "C"
{
int loadbmp(char *filename, unsigned char **buf,
int *w, int *h, int pf, int bottomup);
const char *bmpgeterr(void);
}
unsigned char *srcBuf=NULL, **jpegBuf=NULL;
unsigned long jpegsize=0;
int width, height;
char *filename={"Screenshot158139.bmp"};
tjhandle handle=NULL;
void main(){
if(loadbmp(filename, &srcBuf, &width, &height,TJPF_RGB, 0)==-1){
//printf("Could not load bitmap: %s\n", bmpgeterr());
exit(1);
}
if((handle=tjInitCompress())==NULL) {
printf("Could not initialize compressor: %s\n", tjGetErrorStr());
free(srcBuf);
exit(1);
}
if((tjCompress2(handle, srcBuf, width, 0, height, TJPF_RGB,
jpegBuf, &jpegsize, TJSAMP_444,10, 0))==-1) {
printf("Could not compress: %s\n", tjGetErrorStr());
free(&srcBuf);
tjDestroy(handle);
exit(1);
}
}
The problem I get from this is that I need to resolve the extern "C" code I think:
error LNK2001: unresolved external symbol loadbmp
Sadly, I don´t know how to do that, and as this error is extremely common in the C++ world, finding an answer for this is not that easy as they can differ.
Hopefully it´s pretty easy to solve this, as I guess I must define it or something as it´s external code.

It seems you have declared loadbmp() but you haven't defined it. Where is the function defined? If it is supposed to come from a library, do not declare this function yourself but rather include the relevant header. The documentation of the function should tell you which is the relevant header and it should mention which extra libraries you may need to include.
If loadbmp() isn't function you want to take from a library, you need to define (implement) it.

What you are missing is linking to your .lib file. Often a quick and easy way is to add this line to the top of the file
#pragma comment(lib,"put_your_lib_filename_here.lib")

Related

unresolved external symbol, ATIDAQ, VisualStudio

I'm extremely confused and have been going in circles for about the past hour with this now.
I am attempting to add the ATIDAQ C Library to my project zip link here for the ATIDAQ C Library. In my project I have added:
C/C++->General->Additional Include Directories: <PATH_TO_LIB>\ATIDAQ C Library\ATIDAQ
However I keep getting the error LNK2001: unresolved external symbol _createCalibration
main.cpp
extern "C" {
#include <ftconfig.h>
}
int main(int argc, char* argv[]) {
char *calfilepath; // name of calibration file
unsigned short index; // index of calibration in file (second parameter; default = 1)
Calibration *cal = NULL; // struct containing calibration information
unsigned short i, j; // loop variables
index = 1;
calfilepath = argv[1];
cal = createCalibration(calfilepath, index);
printf(" Serial: %s\n", cal->Serial);
printf(" Body Style: %s\n", cal->BodyStyle);
}
Which is I think caused by the line C/C++->General->Additional Include Directories: <PATH_TO_LIB>\ATIDAQ C Library\ATIDAQ. The IDE finds the Calibration *createCalibration(char *CalFilePath, unsigned short index); function (as this is not syntax highlighted and tab completes).
I'm really unsure what is going, wrong. I think I am missing something with the linker, but I am just not sure as to what.
The ATIDAQ C Library doesn't provide a .lib for you to link against; instead, you should instruct the Visual C++ compiler to compile the necessary C source files in the same folder. In this case, createCalibration is implemented in ftconfig.c.

"Unresolved external symbol" for templated function declared inline in header

I have a Visual Studio 2012 project equivalent to this:
Header.h
template< class T >
inline int Demonstrate( const char *txt, T *input )
{
return printf("%s %d %f\n", txt, input->Integer(), input->Real() );
}
Source.cpp
#include "Header.h"
class Foo
{
public:
int Integer() { return 2; }
float Real() { return 3.14159f; }
};
int main()
{
Foo example;
printf( "%d\n", Demonstrate( "foo:", &example ) );
return 0;
}
Yet when I compile I receive a LNK2019 error:
unresolved external symbol "int __cdecl Demonstrate(char const *,class Foo *)"
Ordinarily this occurs when a templated function is declared in a header but only defined in a cpp, but that is not the case here. The function is defined inline in the header.
What could cause this and how can I fix it?
edit
This happens even if I remove the header altogether and just stick Demonstrate() at the top of Source.cpp. It happens whether "Inline Function Expansion" in the project properties is set to "Default" or to "/Ob2" . This must be some project settings thing, but what?
So I tracked this down and it turns out that Joel was on the right path. The function Demonstrate() had been prototyped multiple times in multiple headers — in a very nonobvious way. There was the explicit int Demonstrate( const char *txt, Foo *input ) declaration, which is what I replaced with a template.
But there were several other headers that had, strewn across them, something analogous to this (you can infer that the actual function and class names were much more complicated):
header a.h:
#define FUNC_PREFIX Demo
header b.h:
#define REGISTER_CLASS( retype, classname, FUNC_SUFFIX ) retype FUNC_PREFIX ## FUNC_SUFFIX ( const char *txt, classname *ptr )
header c.h:
REGISTER_CLASS( int, Foo, nstrate );
REGISTER_CLASS( int, Bar, nstrate );
// etc
I'm not sure what to draw from this. On the one hand it's a very specific bug to a very specific codebase and too localized to be a useful SO question. On the other hand, there is a teachable moment here:
DON'T USE MACROS TO DEFINE GLOBAL FUNCTIONS IN SNEAKY WAYS.
Or else poor saps like me will spend hours tracking down problems like this.
Sometimes you can't rely on automatic template specialization. I've encountered this before with VS and ended up having to be explicit. ie
Demonstrate<Foo>("foo:", &example)

How to create Qt-based Library That Can Be Called from C

I'm trying to build a simple library that uses some of Qt's functionality (no event loop, just some image manipulation and file loading) and then call that library from a standard C program. I've reviewed the answer here, but the answer did not provide enough information for me to resolve the problem. I have built the library as a static library to be linked, and wrapped the function calls with extern "C", but I get a bunch of errors, starting with /usr/include/QtCore/qnamespace.h:-1: In function ‘QT_MODULE’:/usr/include/QtCore/qnamespace.h:54: error: unknown type name ‘namespace’.
Does anyone have a short tutorial on linking to Qt libraries from a C program? FYI, everything is under Linux (Fedora 15), and both the C program and the Qt library are being built with QtCreator.
Lets say you want to make a wrapper for creating and deleting QImage, it could be done something like this:
In your header file:
typedef void *my_qimage_t;
extern "C" my_qimage_t my_create_qimage(int width, int height);
extern "C" void my_delete_qimage(my_qimage_t image);
And in your source file:
extern "C" my_qimage_t my_create_qimage(int width, int height)
{
QImage *qimage = new Qimage(width, height);
return static_cast<my_qimage_t>(qimage);
}
extern "C" void my_delete_qimage(my_qimage_t image);
{
QImage *qimage = static_cast<QImage *>(image);
delete qimage;
}
The my_qimage_t type is, from the callers perspective, a black box. All manipulation has to be done through your library, by passing this opaque pointer around.

C++ link error LNK2005

I am new to C++ programing and I'm trying to make a program that simulates Conway's game of life. I'm almost done but when I made each function have it's own file I keep on getting this linker error.
1>algorithm_change.obj : error LNK2005: "unsigned short height" (?height##3GA) already defined in algorithm.obj
My code is at https://github.com/rupertsteel/Life/tree/master/Life
Without looking at the code, do you have a global unsigned short height; in any header file? If yes, replace that with extern unsigned short height; and put a unsigned short height; in a source file that includes the specific header.
A few comments:
1) array_length in life.h needs to be externed
2) All the externed variables (width, height, ticks, count_array, change_array, error_check, algorithm_length, array_length) need to be defined somewhere.
In your code you've basically told the compiler that those variables exist somewhere but haven't actually placed them in existence anywhere. In one of your .cpp files in the global scope you need to put:
unsigned short int width;
unsigned short int height;
unsigned long int ticks;
unsigned short int count_array[10923][10923];
bool change_array[10923][10923];
int error_check;
unsigned long int algorithm_length;
unsigned long int array_length;
Which is exactly the same as what you have in life.h, except without the extern keyword. This will actually create the variables, as opposed to now where they have no concrete implementation.
If you make the changes I suggest your code will compile (tested using gcc). That being said, the actual error you're seeing doesn't make sense.

C++ Windows Plugins - Passing Classes

I am working on a plugin system in C++ whereby a C++ executable loads a dll and runs plugin_start(someclass&) via GetProcAddress.
I fully understand how to pass function pointers to the dll, and visa versa, and how the dll may use anything defined in a header file, but I would like the dll to be able to use someclass where someclass is declared in someclass.h BUT DEFINED in someclass.cpp.
The catch is, someclass is compiled into the calling executable which means when the dll tries to call a function it gets a linker error. I even understand why this is, what I don't understand is how to achieve what I want.
I imagine I can pass a pointer to the object, and a pointer to the function ie someclass* somefunction* and then call it as someclass->*somefunction() but this means I would have to pass a pointer to every function in every class.
Is there an easier way to do this, or should I stick to C-style functions and function pointers alone and forget trying to pass entire classes between the two?
Thanks,
Ben
#ifndef EVENTREGISTRAR_H
#define EVENTREGISTRAR_H
#include <vector>
typedef void (__stdcall *error_callback_t)(const char *error);
class EventRegistrar
{
public:
void OnError(error_callback_t fn);
void FireError(const char *error);
private:
std::vector<error_callback_t> errors;
};
#endif
-- Cpp
#include "PluginLoader.h"
void EventRegistrar::OnError(error_callback_t fn)
{
this->errors.push_back(fn);
}
void EventRegistrar::FireError(const char *error)
{
for (std::vector<error_callback_t>::iterator it = this->errors.begin();
it != this->errors.end(); ++it)
{
(*it)(error);
}
}
-- DLL
#include "../plugin.h"
#include <stdio.h>
void __stdcall error(const char *error) { printf("Error: %s\n",error); }
extern "C" int __stdcall plugin_start(plugin_start_data& data)
{
error_callback_t fn = error;
data.events.OnError(fn);
return LOAD_SUCCESS;
}
--Error
Error 1 error LNK2001: unresolved external symbol "public: void __thiscall EventRegistrar::OnError(void (__stdcall*)(char const *))" (?OnError#EventRegistrar##QAEXP6GXPBD#Z#Z) D:\Files\C++ Workspace\BLib\BLib\Example Plugin\main.obj Example Plugin
I did something like this a long time ago. I simply used a straight C interface to keep things simple.
There may be a better way but I think passing a pointer to the object is your best and most straight-forward approach.