|
Hi,
I recently started my first project based around DLLs and have run into a little trouble.
I followed this tutorial: http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c9855
The code is split up into a header file and a source file.
It consists of a namespace, which contains variables and a class.
I am linking implicitly.
In a test program I can access the variables fine, no problems there, but when I use a function from the class, I get linker errors, eg:
<pre>1>ELQTest.obj : error LNK2019: unresolved external symbol "public: static bool __cdecl ELQ::Functions::CreateRot(void)" (?CreateRot@Functions@ELQ@@SA_NXZ) referenced in function _SDL_main</pre>
Now for some code:
DLL Header:
#ifndef _ELQDLL_H_
#define _ELQDLL_H_
#include <SDL.h>
#include <cmath>
#include <windows.h>
#pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib")
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
namespace ELQ{
extern "C"{
#pragma data_seg (".globals")
DECLDIR bool keyboard[27], open;
DECLDIR double sins[720], coss[720], v, posx, posy, posz, f, h;
DECLDIR int WIDTH, HEIGHT, DEPTH, BPP, q, speed, theta, *map, o, lx1, ly1, lx2, ly2, lx3, ly3;
class Functions{
public:
static bool CreateRot();
};
}
}
#endif
DLL Source:
#include "ELQDLL.h"
#define DLL_EXPORT
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
namespace ELQ{
extern "C"{
#pragma data_seg (".globals")
DECLDIR bool keyboard[27], open = false;
DECLDIR double sins[720], coss[720], v, posx, posy, posz, f = 10, h;
DECLDIR int WIDTH, HEIGHT = 10, DEPTH, BPP, q, speed, theta, *map = NULL, o, lx1, ly1, lx2, ly2, lx3, ly3;
DECLDIR bool CreateRot(){
for(int x = 0; x < 720; x++){
sins[x] = sin((x-360)*0.017);
}
}
}
#include "stdafx.h"
#include "ELQDLL.h"
#include <iostream>
SDL_Surface *screen;
int main(int argc, char *argv[]){
if(ELQ::Functions::CreateRot())
system("PAUSE");
return 0;
}
Any idea what could be wrong?
I've played around with all sorts of combinations of class definitions, export/import symbols etc, yet cannot get this to work.
Look forward to your input,
Thanks,
Nat.
PS: Oh, I should say that when I compile the DLL, I get a stream of inconsistency messages, could this be related?
"Sir, I protest. I am NOT a merry man!"
|
|
|
|
|
Those extern "C" statements look wrong - especially as a) you're using namespaces and b) you're enclosing class definitions in them. Now, namespaces and classes are C++ features - they really aren't compatible with extern "C" , which specifies that the names enclosed by the extern "C" are exported as undecorated, C names rather than decorated C++ names.
BTW - a decorated C++ name is something like ?CreateRot@Functions@ELQ@@SA_NXZ , your missing symbol...
So - try removing all extern "C" things. The only reason for extern "C" is to export functions compiled with a C++ compiler in a form compatible with C. You're exporting namespaced functions and classes - they will never be compatible with C...
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Thank you very much!
I feel like a total fool now, though. Classes in C?! They should revoke my C++ licence for that.
"Sir, I protest. I am NOT a merry man!"
|
|
|
|
|
Don't sweat it man - we've all done it one time or another!
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
See I have a SDI app with a (e.g.) CEditView drieved view. Now I want to create another view of my document, drived from (e.g.) CRichEditView. I dislike the user to have a splitter window at the execute time, but when pressing a menu item. can I use CFrameWnd::CreateView? how if yes?
Thank you masters!
|
|
|
|
|
Do you want to display both views at once (in which case having a splitter is really the best idea) or one view at a time?
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Yes, both at once
Thank you masters!
|
|
|
|
|
Since CRichEditView is derived from CView you must use CRichEditView::Create (Actually CWnd::Create ) and then use CDocument::AddView . CFrameWnd::CreateView is for views that are not derived from CView .
«_Superman_»
I love work. It gives me something to do between weekends.
|
|
|
|
|
class Employee {
public:
Employee(string name = "No Name",
string id = "000-00-0000",
double salary = 0)
: _name(name), _id(id)
{
_salary = salary;
}
...
};
I'm not sure what the [ : _name(name), _id(id) ] does. Can anyone please explain?
Thanks
|
|
|
|
|
They're initializer shortcuts for your member variables. Those statements are the same as saying
_name = name;
_id = id; immediately within your constructor body.
|
|
|
|
|
Quick follow up:
: _name(name), _id = id
{
_salary = salary;
}
Shouldn't I be able to do this?
Thanks
|
|
|
|
|
That's not allowed, see, for instance [^].
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
No, but you can do this.
: _name(name)
{
_id = id;
_salary = salary;
}
The difference is that _name(name) is initialization and _id = id is assignment.
This is equivalent to
type _name = name; and
type _id;
_id = id;
«_Superman_»
I love work. It gives me something to do between weekends.
|
|
|
|
|
Hello su_penguine,
Its called constructor initializer list. Check this[^] and this[^] for more information.
Regards,
Jijo.
_____________________________________________________
http://weseetips.com[ ^] Visual C++ tips and tricks. Updated daily.
|
|
|
|
|
Does anyone know why Skype seems incompatible with Vista Home edition?
Sorry its not a C++ question. But you guys are the best.
|
|
|
|
|
Ric Ashton wrote: Does anyone know why Skype seems incompatible with Vista Home edition?
Because your question is incompatible with this forum.
Better place to ask :Here[^]
He never answers anyone who replies to him. I've taken to calling him a retard, which is not fair to retards everywhere.-Christian Graus
|
|
|
|
|
Ric Ashton wrote: Sorry its not a C++ question.
You are indeed correct.
|
|
|
|
|
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
C is my preferred programming language. I know it is not the expected answer, but since you're our fan...
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
The first 2 books didn't address these issues and the third book assumes the reader has the following knowledge, so I turn to codeproject for the answers, google came up with mixed results for some of the following, so I was hoping a community with experience could sum it up nicely instead of working through google more then what I have,
What exactly are the following datatypes
1. Handle
2. PVOID
3. DWORD
Also, a general question, why use pointers (*) if you can use Addresses (&) to reference objects?
|
|
|
|
|
1,2 and 3 are not C++ types. They are code defined types so you should be able to go to the definition using the IDE tools you are working with.
The general rule I go by is to only use pointers when absolutely necessary. Mostly this translates to when it has been determined that using the heap is required. Also translates to when a reference type will not satisfy the requirements.
|
|
|
|
|
Handle : Handle to an object. It may point to any object. For example a Handle to a window.
PVOID is nothing but a void*. "P" means a pointer.
DWORD is 32 bit unsigned integer.
EliottA wrote: Also, a general question, why use pointers (*) if you can use Addresses (&) to reference objects?
The general answer is , if you can use & do not use *. Moreoever you can send * as *&.
He never answers anyone who replies to him. I've taken to calling him a retard, which is not fair to retards everywhere.-Christian Graus
|
|
|
|
|
You need to buy the complete reference book.
Something like the 'The Waite Group's' Turbo C++ Bible, or
something more up-to-date.
Utilising DWORD (for example) is a complex issue reserved for
programmers with some experience.
To find out what it is used for and how it is used you might
involve yourself with the complex issue of 'sound' and search
the internet for applicable code in this area.
I think this is why nobody had yet replied.
|
|
|
|
|
EliottA wrote: What exactly are the following datatypes
1. Handle
2. PVOID
3. DWORD
See here.
EliottA wrote: Also, a general question, why use pointers (*) if you can use Addresses (&) to reference objects?
See here.
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
|
|
|
|
|
|