Error while making DLL

Pages: 12
so I tried to find some youtube videos on how to make a DLL, I found one, I also found several topics (like on msdn and stuff), but I have this code

header
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#include <string>
using namespace std;

#pragma comment(lib, "ws2_32.lib")

#define WM_PATH_DNS (WM_USER + 1)
#define WM_PATH_DATA (WM_USER + 2)

#define BUFSIZE 10240
#define TEXT_SIZE 102400

class PathSocket
{
	static __declspec(dllexport) char cBuffer[MAXGETHOSTSTRUCT], cTextBuffer[TEXT_SIZE];
	static __declspec(dllexport) HANDLE hIDTask;
	static __declspec(dllexport) SOCKET *socket;
public:
	static __declspec(dllexport) int Init(int, HWND, char*);
	static __declspec(dllexport) int SendBuffer(char*, SOCKET, int, int);
};


source
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "PathSocket.h"

int PathSocket::Init(int iSockets, HWND hWnd, char* cDomainName)
{
	socket = new SOCKET[iSockets];

	WORD wVersionRequested = MAKEWORD(2,2);
	WSADATA data;

	if (WSAStartup(wVersionRequested, &data) != 0)
		return 0;

	memset(cBuffer, 0, MAXGETHOSTSTRUCT);

	if ((hIDTask = WSAAsyncGetHostByName(hWnd, WM_PATH_DNS, cDomainName, cBuffer, MAXGETHOSTSTRUCT)) == 0)	
		return 0;

	return 1;
}

int PathSocket::SendBuffer(char* buff, SOCKET sock, int len, int flags)
{
	return send(sock, buff, len, flags);
}


and I'm getting these errors:

1>error LNK2001: unresolved external symbol "private: static char * PathSocket::cBuffer" (?cBuffer@PathSocket@@0PADA)
error LNK2001: unresolved external symbol "private: static unsigned int * PathSocket::socket" (?socket@PathSocket@@0PAIA)
error LNK2001: unresolved external symbol "private: static void * PathSocket::hIDTask" (?hIDTask@PathSocket@@0PAXA)


any suggestions? also could someone explain me WHY is there static, and what does dllimport/dllexport does? also there are NO tutorials with variables inside dll >.<

I've been following this http://msdn.microsoft.com/en-us/library/ms235636.aspx and the video I already lost, however there's no
1
2
3
4
5
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport) 
#else
#define MATHFUNCSDLL_API __declspec(dllimport) 
#endif 

in the video, why do we have to use that?

http://msdn.microsoft.com/en-us/library/ms235636.aspx

or more simply, could someone link me a proper up to date tutorial, where's EVERYTHING explained, to the very detail?
Last edited on
http://www.cplusplus.com/forum/general/113904/#msg622050

> WHY is there static
there `static' refers to class members/methods, you don't need an object to access them (in that case all the objects would be equivalent as they do not have state)
I don't know if that is a must to create DLL,
well, I just created BASIC class, without all this dllexport stuff, and it's working just fine (when using header + lib)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#include <string>
using namespace std;

#pragma comment(lib, "ws2_32.lib")

#define WM_PATH_DNS (WM_USER + 1)
#define WM_PATH_DATA (WM_USER + 2)

#define BUFSIZE 10240
#define TEXT_SIZE 102400

class PathSocket
{
	char cBuffer[MAXGETHOSTSTRUCT], cTextBuffer[TEXT_SIZE];
	HANDLE hIDTask;
	SOCKET *socket;
public:
	int Init(int, HWND, char*);
	int SendBuffer(char*, SOCKET, int, int);
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "PathSocket.h"

int PathSocket::Init(int iSockets, HWND hWnd, char* cDomainName)
{
	socket = new SOCKET[iSockets];

	WORD wVersionRequested = MAKEWORD(2,2);
	WSADATA data;

	if (WSAStartup(wVersionRequested, &data) != 0)
		return 0;

	memset(cBuffer, 0, MAXGETHOSTSTRUCT);

	if ((hIDTask = WSAAsyncGetHostByName(hWnd, WM_PATH_DNS, cDomainName, cBuffer, MAXGETHOSTSTRUCT)) == 0)	
		return 0;

	MessageBox(hWnd, "Init Successfull!", "Success!", MB_ICONINFORMATION);
	return 1;
}

int PathSocket::SendBuffer(char* buff, SOCKET sock, int len, int flags)
{
	return send(sock, buff, len, flags);
}


is there anything wrong on the way I'm doing it? or is this completely ok?
Last edited on
Visual studio automatically defines a macro which is your project name (all caps) and appends "_EXPORTS", I use this in the header for my dlls because of this useful thing.

Demo.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma once

#ifdef DEMO_EXPORTS
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#pragma comment(lib, "Demo.lib")
#endif

namespace Demo{
    DLL <type> function(<arguments>);
    
    class DLL name{
        //Class stuffs
    };
}


I'm sure you know what would go in the c file.

How this works is that as long as your compiler knows where the lib and dll files are it'll automatically load them when you include the header file, once you've exported the dll you don't even need the source file for any projects compiled with this library as it just adds a section into your program asking it to use the dll
Last edited on
wow, really? I appreciate the help, but did u at least read the thread?

any suggestions? also could someone explain me WHY is there static, and what does dllimport/dllexport does? also there are NO tutorials with variables inside dll >.<

I've been following this http://msdn.microsoft.com/en-us/library/ms235636.aspx and the video I already lost, however there's no

1
2
3
4
5
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport) 
#else
#define MATHFUNCSDLL_API __declspec(dllimport) 
#endif  



in the video, why do we have to use that?


you did the very same thing as msdn, told me to use that thing there and didnt even mention what the hell it does, or why it should be there, also I wrote my lib just like any other .cpp/.h, so no headers or anything, just pure class and functions, and it works just fine,is it bad?
Okay, my bad, sorry for not reading that one but I can explain a little more now...

Basically __declspec(dllexport) is the simplest way of asking the compiler to export the function or class into a dll file, __declspec(dllimport) tells the compiler that it can find this function inside a dll file...
This is why it's good to use a macro for them because when you're working on the project DLL will be defined as __declspec(dllexport) so that when you hit compile it transfers the working code into a dll, when you're not working on the project, and instead you are just including the header DLL will be defined as __declspec(dllimport), so this tells the compiler to import the working functionality from the dll.

You are getting the Unresolved External errors because in the header you're asking the compiler to export 5 functions, but in the source file you've only defined 2 of them... Leaving you with 3 missing (or "unresolved external") functions/variables.
Everything that you declare in a header for exportation (whether to a dll, exe, lib, etc) must be defined somewhere.

Dll's with variables inside? Well I've just said that everything must be declared and defined for exportation... Same with variables.
You can declare a variable in the header using the "extern" keyword to indicate that a variable exists, but isn't in this file. extern int num1; You have to define the variable outside of the header otherwise when you include the header you'll get an error saying "multiply defined (something or other)"... The source file is only used once and this is on the compilation of your dll, so this would be a perfect place to define the variable for exportation.
SO, DLL extern int num1; in your header, and int Demo::num1; in your cpp.

As for the static functions, this is an easy one XD
If you've noticed when I showed my example I used namespace Demo, this way I can keep my code separated from other things easily, but if I wish to declare any functions I have to write DLL in front of all of there declarations.
However when you define a class to be exported you only need the DLL to be after the class keyword, then everything that makes up the class will be exported to dll... Static functions can be called without having any class instances by using the namespace operator.


1
2
3
4
5
//Demo.h
namespace Demo{
    DLL void print1();
    DLL void print2();
}


The above is using namespaces, and now using classes:

1
2
3
4
5
6
//Demo.h
class DLL Demo abstract{
public:
    static void print1();
    static void print2();
};


The cpp file for both of these would be EXACTLY the same

1
2
3
4
5
6
7
//Demo.cpp
void Demo::print1(){
    printf("1");
}
void Demo::print2(){
    printf("2");
}


(And if you're wondering about the "abstract" keyword on the class, don't worry about it... I've just put it there because there would be no reason to create an instance of this class, abstract stops any instances)
Just to be complete I should also mention that both the namespace declaration AND the class declaration can call functions in the same way...
Demo::print1();

I hope that's cleared a few things up?

EDIT: Oh yeah, I say
is the simplest way of asking the compiler to export the function or class into a dll file
because there is more than one way (but this is easiest)... There are methods that export a dll so it has a main function that is called when the library is loaded/unloaded and with the reasons why, and you can do (very limited) things with this. I believe this method produces a function definition file or something? I shouldn't really go into it because I don't know much about this method, I'm sure if you needed it you'd be able to find it on MSDN
Last edited on
Why you complicate itself and don't use Visual Studio wizard for making DLLs ?

Other IDEs like Code::Blocks has the wizard too ...


You could learn what these do and try to replicate itself afterwards. Youtube videos is a bad thing, you will not learn anything from them.
1.
Basically __declspec(dllexport) is the simplest way of asking the compiler to export the function or class into a dll file, __declspec(dllimport) tells the compiler that it can find this function inside a dll file...


I dont have this, I just have basic class http://pastebin.com/8Q2smTBW and it's working just fine (I'm not using DLL tho, but .h + .lib, does this mean a .dll wont work, and so I have to use export/import to make it work?)

2.
This is why it's good to use a macro for them because when you're working on the project DLL will be defined as __declspec(dllexport) so that when you hit compile it transfers the working code into a dll, when you're not working on the project, and instead you are just including the header DLL will be defined as __declspec(dllimport), so this tells the compiler to import the working functionality from the dll.


so when I'm creating a DLL it will dllexport, and when I'm using a DLL from another application, it will dllimport, right?

3.
You are getting the Unresolved External errors because in the header you're asking the compiler to export 5 functions, but in the source file you've only defined 2 of them... Leaving you with 3 missing (or "unresolved external") functions/variables.
Everything that you declare in a header for exportation (whether to a dll, exe, lib, etc) must be defined somewhere.


actually, those 3 undeclared are variables, not functions, so there shouldn't be any error (again, with pure class without all this dll import export stuff it works just fine)

4.
Dll's with variables inside? Well I've just said that everything must be declared and defined for exportation... Same with variables.
You can declare a variable in the header using the "extern" keyword to indicate that a variable exists, but isn't in this file. extern int num1; You have to define the variable outside of the header otherwise when you include the header you'll get an error saying "multiply defined (something or other)"... The source file is only used once and this is on the compilation of your dll, so this would be a perfect place to define the variable for exportation.
SO, DLL extern int num1; in your header, and int Demo::num1; in your cpp.


so I need to treat variables just like functions, and declare them in cpp too? (e.g. (check my source code) int PathSocket::iSockets;)

5.
As for the static functions, this is an easy one XD


actually I dont need static functions (what is static function btw? I know only what is static variable, not a function), the static keyword was just in the tutorial and I have no idea why it is there...

okay, so basically my code modified to dll should look like this, right?

header: http://pastebin.com/y2MLV5vS
source: http://pastebin.com/i3JvdP6H

is there something wrong?

also for the header

1
2
3
4
5
6
7
8
#pragma once
 
#ifdef DEMO_EXPORTS
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#pragma comment(lib, "PathSocket.lib")
#endif 


what is #pragma once doing ?

why is there #ifdef DEMO_EPORTS (if DEMO_EXPORTS is defined? if it means this, where did I define DEMO_EXPORTS in the code, so the compiler knows to export it?)

[code]#pragma comment(lib, "PathSocket.lib")[code]

okay, how can the compiler include PathSocket.lib before it compiles it? why is it there anyway? what is the purpose of this line (I know it includes lib, but why is it in the DLL code, when this should go to the app I want to use lib in, also why is there .lib when I want to use .DLL, not a .lib?)
actually, those 3 undeclared are variables, not functions, so there shouldn't be any error

[...]
so I need to treat variables just like functions, and declare them in cpp too? (e.g. (check my source code) int PathSocket::iSockets;)


In C++, if you have a static class data member declared in your class, then you need a separate definition statement.

So, in your header:

1
2
3
4
class myClass
{
  static double myStaticVar_;
}


and in your source file, at file scope:

double myClass::myStaticVar_ = 1.2345; // You can initialise it here too
If you look you've answered most of your questions yourself when using my quotes so I'll try keep this one simple just to tidy the ideas up a little.

1
(I'm not using DLL tho, but .h + .lib, does this mean a .dll wont work, and so I have to use export/import to make it work?)

Honestly I'm not entirely sure what you mean by this, if you mean you're not using the macro then why not just add it in? Can save a lot of effort replacing dllexport with dllimport.

2
so when I'm creating a DLL it will dllexport, and when I'm using a DLL from another application, it will dllimport, right?

Exactly (enough said?)

3
actually, those 3 undeclared are variables, not functions

Don't matter, I've mentioned that variables must be defined externally as well as the functions


4
actually I dont need static functions (what is static function btw? I know only what is static variable, not a function)[/quote
If you're using the namespace method, or the class you're exporting is designed to be instanced and the function is working on an instance then no you don't need static.
Static let's classes share variables, you said you know about this, but a function by default is also limited to a specific class instance just like it's variables, a function can only operate on the static functions do not need an instance and hence cannot work on non static variables because they require a specific instance. I hope that ain't too confusing?

5
[quote] what is#pragma once doing ?

This is a nice touch to visual studio (and some other compilers) it's just a header protection to make sure you're not defining everything again if the header is included more than once

6
#pragma comment(lib, "PathSocket.lib")[code]

okay, how can the compiler include PathSocket.lib before it compiles it?

Remember the #ifdef PROJECT_EXPORTS? There's an #else with this meaning that the lib is only included if you're including the header instead of working on this project.
Now assuming that you're not going to include the header in the first place until you've finished working on what it's actually for, then you should be pretty safe. Since you'd compile the dll first and then include it afterwards into anything else you need it with.

Most people do just leave it with the DLL to make things easy but I then the programmer has to choose which lib they want to include and do that everywhere they've used the header (well not everywhere but it's for safety, and it only gets loaded once in this method, I think)
I'd rather not have to follow up all the headers with the library comment so I just put it in the header, but you gotta make sure that it's not being used when it's not needed, that's why I've used it inside the macro test statements.
Last edited on
Sorry that's as far as I can get and then my phone's screwing up with the text field and I can't type so I'll edit to finish off when I get on PC

EDIT: Okay I've finished the previous post, sorry about that... (stupid phone)
Last edited on
Honestly I'm not entirely sure what you mean by this, if you mean you're not using the macro then why not just add it in? Can save a lot of effort replacing dllexport with dllimport.


actually, I'm not using dllexport/dllimport at all, or macro, I just have a class and that's it, like this

1
2
3
4
5
6
7
8
9
10
11
class myclass
{
	int a;
public:
	int returnA();
};

int myclass::returnA()
{
	return a;
}


and I'm compiling it into .lib, and I can use that .lib with .h just fine, so I dont need to use dllimport/dllexport (for a LIB, NOT DLL), so my question is: is the dllexport/dllimport (and the macro) only needed for the DLL ? because well, my .lib is working fine

If you're using the namespace method, or the class you're exporting is designed to be instanced and the function is working on an instance then no you don't need static.
Static let's classes share variables, you said you know about this, but a function by default is also limited to a specific class instance just like it's variables, a function can only operate on the static functions do not need an instance and hence cannot work on non static variables because they require a specific instance. I hope that ain't too confusing?


actually it is really confusing :D so basically when I use static I'm setting the function to work only in noninstanced member, e.g. calling Class::Function() from application, instead
1
2
Class a;
a.Function();

or did I udnerstand it totally wrong?

Remember the #ifdef PROJECT_EXPORTS? There's an #else with this meaning that the lib is only included if you're including the header instead of working on this project.
Now assuming that you're not going to include the header in the first place until you've finished working on


so it will include lib only when I use DLL in some application, right? but now to other questions:

a, if DEMO_EXPORTS is defined, it will include lib - where should I define DEMO_EXPORTS in the code? and in what code should I define it? (DLL or app code (when using DLL))

b, when Im using DLL in an app, it will include the lib, HOWEVER when I compile DLL (project properties > general > config type > dynamic library) it WONT make a .lib, so I need to compile both, dynamic AND a static library?
Last edited on
so my question is: is the dllexport/dllimport (and the macro) only needed for the DLL ?


Erm, yup!
If you look back to your first post you have asked about all this stuff though, but yeah a dll is for dynamically linking libraries. i.e. You can section off a little piece of code into it's own little box (the dll), and any other programs that need that functionality can use this little box program, the idea is that if you have a lot of completely different programs (take different games for example), but lets say they all have pieces of code in common (maybe a maths/physics library) then you can place that into a dll and decrease your program size because they can all share this dll rather than having the libraries hard-coded into each program repeatedly.

dlls also have other benefits over static libraries (.lib, .h)... Lets say you've made a software that's sold thousands of copies but you realise later there's a tiny bug somewhere, or maybe you've just optimised the code so it works faster. Static libraries compile to just an .exe file and all your stuff's in there, if you've got a big program it may take ages for people to download an update for this, and also you've got to export the entire project again...
However if you're program's wisely split into smaller programs (.exe, .dll, some runtime scripts), and this certain thing that you're changing (the optimising/fixing a bug mentioned) is only in one or two of these smaller dlls, then you can just redo those libraries (provided only that function bodies are changes, nothing else), and update those tiny parts of the program...
It's now much easier for you and your buyers to be happy updating.

so basically when I use static I'm setting the function to work only in noninstanced member, e.g. calling Class::Function() from application

Exactly, sorry I would've posted code but have you tried coding on an android keyboard?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Foo{
public:
    static void Print1(){printf("%d", &Var1);}
    void Print2(){printf("%d", &Var2);}
    static int Var1;
    int Var2;
};

main(){
//Static members and functions accessed using the namespace operator ::
    Foo::Var1 = 5;
    Foo::Print1();
    
//Local members and functions accessed using the dot operator .
    Foo bar;    //Instance required
    bar.Var2 = 10;
    bar.Print2();
}


a, if DEMO_EXPORTS is defined, it will include lib - where should I define DEMO_EXPORTS in the code? and in what code should I define it? (DLL or app code (when using DLL))

Right, well firstly if your project is called "PathSocket" and you're using MSVS (I did mention this, for any other compiler you'll have to check there definitions) you'll have PATHSOCKET_EXPORTS automatically defined for you while ever you're working on "PathSocket.sln" (if you don't use MSVS .sln is just there project file extension)

Whether you're creating JUST a .lib, or a .dll AND it's .lib you can use the #pragma comment(lib, "PathSocket.lib") in the header like so:
(For exporting to dll)
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifdef PATHSOCKET_EXPORTS
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#pragma comment(lib, "PathSocket.lib")
#endif
[code]

(For JUST the lib)
[code]
#ifndef PATHSOCKET_EXPORTS
#pragma comment(lib, "PathSocket.lib")
#endif 


So, now if you're NOT wanting to make a dll you need to do the following:
Project Properties > General > Config Type > Static Library
This creates JUST a .lib that is able to be linked into a program

b, when Im using DLL in an app, it will include the lib, HOWEVER when I compile DLL (project properties > general > config type > dynamic library) it WONT make a .lib, so I need to compile both, dynamic AND a static library?

I've had this happen to me before if I've tried to export something to dll without actually declaring anything to be under the "declspec", if you have used "declspec(dllexport)" OR you've used this in a macro then I'm afraid this one is a problem I don't know about.
Last edited on
so basically a difference between static and dynamic lib is that with static I have to rebuild whole program, but with dynamic I just have to replace .dll, right?

Right, well firstly if your project is called "PathSocket" and you're using MSVS (I did mention this, for any other compiler you'll have to check there definitions) you'll have PATHSOCKET_EXPORTS automatically defined for you while ever you're working on "PathSocket.sln" (if you don't use MSVS .sln is just there project file extension)


so the PATHSOCKET_EXPORTS consist of a name of solution (or project?) and a _EXPORTS suffix and is hidden somewhere in the project, right? (so I cant see it in source)




okay, so, when I use the macro (or declspec) and im compiling dll, it will automatically make .lib too, right? well, I just added the macro and made my header like this while not changing the source at all, changed output to the dynamic library, but it is not compiling a lib, only dll

edit: also because there's #pragma comment(lib, "PathSocket.lib"), should I include .lib with my .dll everytime I want to use it, or is the .lib IN the .dll?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#include <string>
using namespace std;

#pragma comment(lib, "ws2_32.lib")

#ifdef PATHSOCKET_EXPORTS
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#pragma comment(lib, "PathSocket.lib")
#endif

#define WM_PATH_DNS				(WM_USER + 1)
#define WM_PATH_DATA			(WM_USER + 2)

#define SOCKET_TYPE_CLIENT		0
#define SOCKET_TYPE_SERVER		1

#define SOCKET_SEND_ALL			-1
#define SOCKET_SEND_SPEC		-2

#define BUFSIZE					10240
#define TEXT_SIZE				102400

DLL class PathSocket
{
	char cBuffer[MAXGETHOSTSTRUCT], cTextBuffer[TEXT_SIZE];
	HANDLE hIDTask;
	SOCKET *sock;
	int iType, iSockets, iConnectedSockets;
public:
	PathSocket(int, int);
	~PathSocket();
	int Init(HWND, char*);
	int Connect(HWND, int, LPARAM);
	void SendBuffer(int, char*, int, int);
	char GetBuffer(SOCKET, HWND);
	//TODO
	int AcceptSocket();
	int CloseSocket();
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//PathSocket.cpp
#include "PathSocket.h"

PathSocket::PathSocket(int iSType, int iSckts)
{
	iConnectedSockets = 0;
	iType = iSType;
	if(iType == SOCKET_TYPE_SERVER)
	{
		if(iSckts != NULL && iSckts > 0)
		{
			sock = new SOCKET[iSckts];
			iSockets = iSckts;
		}
		else
			PathSocket::~PathSocket();
	}
	else
		sock = new SOCKET;
}

PathSocket::~PathSocket()
{
	if(iType == SOCKET_TYPE_CLIENT)
		closesocket(*sock);
	else
	{
		for(int i = 0; i < iSockets; i++)
			closesocket(sock[i]);
	}
	iConnectedSockets = 0;
}

int PathSocket::Init(HWND hWnd, char* cDomainName)
{
	WORD wVersionRequested = MAKEWORD(2,2);
	WSADATA data;

	if (WSAStartup(wVersionRequested, &data) != 0)
		return 0;

	memset(cBuffer, 0, MAXGETHOSTSTRUCT);

	if ((hIDTask = WSAAsyncGetHostByName(hWnd, WM_PATH_DNS, cDomainName, cBuffer, MAXGETHOSTSTRUCT)) == 0)	
		return 0;

	return 1;
}

void PathSocket::SendBuffer(int iSendTo, char* buff, int len, int flags)
{
	if(iType == SOCKET_TYPE_CLIENT)
		send(*sock, buff, len, flags);
	else if(iType == SOCKET_TYPE_SERVER)
	{
		if(iSendTo == SOCKET_SEND_ALL)
		{
			if(iConnectedSockets == 0)
				return;
			else if(iConnectedSockets == 1)
				send(sock[0], buff, len, flags);
			else
			{
				for(int i = 0; i < iConnectedSockets; i++)
					send(sock[i], buff, len, flags);
			}
		}
	}
	else
		return;
}

int PathSocket::Connect(HWND hWnd, int port, LPARAM lParam)
{
	struct hostent *host = (struct hostent *)cBuffer;
	struct sockaddr *addr = NULL;
	struct sockaddr_in addr_ip4;
	size_t len = 0;

	//if(WSAGETASYNCERROR((LPARAM)lParam) != 0)
	//	return 0;

	addr_ip4.sin_family = host->h_addrtype;
	addr_ip4.sin_port = htons(port);
	memcpy(&(addr_ip4.sin_addr), host->h_addr_list[0], host->h_length);
	addr = (struct sockaddr *)&addr_ip4;
	len = sizeof(addr_ip4);
	if ((*sock = socket(host->h_addrtype, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
		return 0;

	if (connect(*sock, addr, len) == SOCKET_ERROR)
		return 0;

	if (WSAAsyncSelect(*sock, hWnd, WM_PATH_DATA, FD_READ) == SOCKET_ERROR)
		return 0;

	return 1;
}

char GetBuffer(SOCKET sock, HWND hWnd)
{
	int size;
	char buffer[BUFSIZE];
	if ((size = recv(sock, buffer, BUFSIZE, 0)) == SOCKET_ERROR)
	{
		WSAAsyncSelect(sock, hWnd, 0, 0);
		strncpy_s(buffer, "Error while receiving data!", BUFSIZE);
		send(sock, buffer, strlen(buffer), 0);
		shutdown(sock, SD_BOTH);
		closesocket(sock);
	}
	return *buffer;
}
Last edited on
so basically a difference between static and dynamic lib is that with static I have to rebuild whole program, but with dynamic I just have to replace .dll, right?

Correct

so the PATHSOCKET_EXPORTS consist of a name of solution (or project?) and a _EXPORTS suffix and is hidden somewhere in the project, right? (so I cant see it in source)

Correct again

Try this to see all the automatically declared macros from MSVS
Project > [project] Properties > Configuration Properties > C/C++ > Preprocessor > Preprocessor Definitions

Some definitions are left out from here for some reason though, you can check out this for everything:
"Same again" > C/C++ > Command Line

Anything following
/D 
is a #define symbol, if you wish to add your own make sure you use quotes for the actual macro, i.e.
/D "MIN(x, y) ((x < y) ? x : y)"


===================================================

And as far as I can tell about the actual structure of your code it's all set for creation of the .lib AND .dll combo. (Sorry I can't understand why you're not getting a .lib with it)

When you've set the compiler to output a .lib ONLY then it adds everything into that, and compiles fully into anything that asks for this lib with the pragma comment. (Kinda like you lib contains all your src)

When you've set the compiler to output a .dll, it'll should create a .dll AND a .lib, this time the dll contains all your code functionality and the lib has been only to tell your program how to use the dll file.
(Kinda like your dll contains all your src, and the lib is a special header for it which tells windows how to read from this particular dll)
Last edited on
WAIT, I may know why it's not working properly!
You've put DLL class PathSocket{, whenever I've done this on my compiler the console log reads something like "__declspec(dllexport) ignored in front of class for no defined variable"

When adding __declspec(dllexport) in front of a type the compiler expects to see variable or function. Because at the end of your class declaration you've just ended with this }; there is no variable being declared (don't worry, you don't want one here)

What you actually need to do is move the DLL to here class DLL PathSocket{
When adding __declspec(dllexport) after the class/struct keyword the compiler knows to output the format of the class, it's not looking for variables of that class.

Check your output log, see if I'm right? :D
Last edited on
well I was thinking about this mistake, but I used your code for this

1
2
3
4
5
DLL class Demo abstract{
public:
    static void print1();
    static void print2();
};


anyway I have few more questions:

1, in this code, by you, you showed me the example on how are static functions used in class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Foo{
public:
    void Print1(){printf("%d", &Var1);}
    static void Print2(){printf("%d", &Var2);}
    int Var1;
    static int Var2;
};

main(){
//Static members and functions accessed using the namespace operator ::
    Foo::Var1 = 5;
    Foo::Print1();
    
//Local members and functions accessed using the dot operator .
    Foo bar;    //Instance required
    bar.Var2 = 10;
    bar.Print2();
}


since var2 and print2 are static functions, shouldn't they be used as a

1
2
Foo::Var2 = x;
Foo::Print2();


instead of var1 and print1 ? (so switched, u used not static for noninstanced, and static for instanced if I understood the code right)

2, can namespace have the same name as class? so


1
2
3
4
5
6
7
namespace PathSocket
{
	class DLL PathSocket
	{
		//class stuff
	};
}


3, now the DLL functionality: when Im using DLL in my project, it requires .lib, right? so, do I need to bundle .lib too, with my app, or is dll enough and .lib is coded into app?

Im in school atm and I dont have my project here, so I cant test it, but I will do that after Ill get home, I think that I had more questions than those 3, but I cant remember them now :/
Oh indeed, I'm sorry about that DLL example, and the static example... But hey it does show that at least you're paying more attention than I a.m.

As for the lib + dll. Once you've compiled an app that makes use of a dll I do think that the lib gets compiled into it and you only need to package it with the dll.

(I feel bad for trying to help and getting the code the wrong way round)
Last edited on
np, happens when u're doing it on the phone :D

anyway, can namespace have the same name as class? like this

1
2
3
4
5
6
7
namespace PathSocket
{
	class DLL PathSocket
	{
		//class stuff
	};
}
Yeah, because there's no other way to create an instance of that class other than through it's namespace.

1
2
3
4
int main(){
    PathSocket::PathSocket sock;
    sock.DoStuff();
}


And I'll just go amend my previous codes for use of reference, and I'm not going to blame the DLL class <name>{ on my phone because I constantly do this in my own code and it takes me like half an hour to figure out why (or as soon as I remember to read the actual output log rather than the error log)
Last edited on
Pages: 12