|
Hello pasztorpisti,
After reading your first post a few times I think I have figured out your message.
In the first code block you are describing my error in the OP and providing the Whys of the situation.
In the second code block you are describing the techniques used to access the various components of the object. I did not ask that, but you provided it as a necessary bonus.
Please comment and confirm/deny my interpertation.
Edit: I addressed this to a) recognize him specifically, b) identify the post. However, every reader is invited to respond.
Thanks for your time
modified 30-Sep-12 12:36pm.
|
|
|
|
|
You are welcome! However the cast to (char*) is barely an access of subcomponents, its rather accessing the contents of the object as binary byte array that should be considered as a primitive form of serialization. It might not work if you share the binary data for example between two machines that are different in endianness or if the class/struct member alignment used by the compiler of those systems is different and you don't set alignment explicitly (that isn't always possible)...
Note: In a simple program that isn't crossplatform its okay to serialize data this way. Lets say you write an exe that communicates over sockets with other machines - if all the machines run windows and you copy the same executable to all machines then everything will be fine, it would be a mistake to overcomplicate your serialization in this case. However the problem I wrote about (endianness, alignment) arises much often on linux platform where the underlying machine architectures can differ significantly and the same program has to be recompiled.
modified 30-Sep-12 14:42pm.
|
|
|
|
|
Hello,
I have an application exe and COM dll.
- In Exe I have like this :
class CMyExeApp : public CWinApp
{
...
public:
CMyObject * m_pMyObject;
public:
virtual BOOL InitInstance();
....
}
extern CMyExeApp theApp;
All works fine between the Exe and the COM dll.
What I need is to get the instance of Class CMyExeApp (theApp) to get the reference to m_pMyObject IN THE DLL
I tried this in Dll :
HMODULE hModule = GetModuleHandle(CURRENT_EXE_NAME);
but i didn't know what i do after
any help please 
|
|
|
|
|
Put an exported DLL function to your DLL that you call from your exe. You could pass the CMyObject pointer to your DLL as a parameter.
|
|
|
|
|
first thanks for reply
But I dont like modifing any thing in code (i should add a new interface for that)
SO i need just to get a pointer to this object.
can I get it by adress or something else?
|
|
|
|
|
If you don't like modifying the code then just leave it as it is.
|
|
|
|
|
Accessing a class residing in another module has many implications. Finding out if your modifications are valid or not can be decided just by looking at the code.
|
|
|
|
|
khaliloenit wrote: but i didn't know what i do after
There is nothing you can do since there is no direct back link from the Windows handle to the class object. You will have to modify both your exe and your DLL to pass the pointer across from one to the other.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
If it's a COM dll then passing a C++ object to it is almost certainly a bad idea; COM is meant to be language neutral. Provide a COM compliant interface to the C++ object and pass that to it.
Steve
|
|
|
|
|
Environment Windows 7, Visual Studio 2008, MFC, C++
Goal: create an asynchronous server and client class to demonstrate a simple server client operation. Base class for Server and Client is CAsyncSocket. IP address 127.0.0.1, port 49000
Status: The dialog has buttons for the server to Initialize, Listen, and Accept, so far. It also has buttons for the client to Initialize and Connect. Both have Close buttons. One dialog but two separate classes. Umm, make that three counting the CAsyncSocket class used by the server to communicate after the two have connected.
In the server group buttons Initialize and Accept appear to work correctly, in that order of course. The returned status is TRUE and wsa error code is zero. The Listen button creates a new object to handle the transactions and gets WSA code 10035 WSAEWOULDBLOKC, would block, treated as an expected result. Good so far. Now, hopefully, the server object is waiting for the client.
Then the buttons for the client are selected to Initialize, wsa error = 0, then Connect to the same IP address and port. It gets wsa error code 10048, WSAEADDRINUSE, address already in use. Hmmm. Yeah, it is in use, but if it is not in use by a server then the client cannot connect.
I believe I have the code working as I expect, but there is a fundamental error in my logic. Is this sufficient info for someone to tell me what I have done wrong or omitted? What might that error be?
Thanks for your time
|
|
|
|
|
Following the OP, and per various tutorials I have found, I have created skeleton methods and virtual overrides everywhere I think there should be one I have also set breakpoints in all these methods. The results are not expected and quite interesting.
Note: The send time class is instantiated in the C_Server::Accept() method called by the Accept button in the dialog and passed into the Accept() method that I think is the one from the base class CAsyncSocket. Is that the correct action to perform?
After clicking the Connect for the Client class, the breakpoint is activated in C_Client::OnConnect( int nErrorCode)
The error code said the port was in use, but I am now thinking that maybe the error code should be expected and considered normal. Maybe I should write code in here for when the connect is successful. Per an example this method has code to call CAsyncsocket::OnConnect( int x ); I presume that is the base class. That function has no code. Should there be anything there?
Click Run in the debugger to see what happens and,…
The breakpoint in C_Server::OnAccept( int error_code ) is called. Thanks to an example I found, it calls CAsyncSocket::OnAccept( error_code ) which again is empty. I am now presuming that despite the earlier error code, the server code, the part within the Windows API that I don’t see, has indeed accepted the connection and it ready to send data to and receive data from the client. Is this indeed the case? If so, is there something that should be done in this method?
Clicking the debugger run one more time,
The breakpoint in C_Client::OnSend( int error_code ) is called.
Now this is puzzling. My code does not send anything. Is this telling me the client is expected to send something to the server? What should it send?
Thanks for your time
-- modified 16-Sep-12 16:45pm.
|
|
|
|
|
bkelly13 wrote: Then the buttons for the client are selected to Initialize, wsa error = 0, then Connect to the same IP address and port. It gets wsa error code 10048, WSAEADDRINUSE, address already in use. Hmmm. Yeah, it is in use, but if it is not in use by a server then the client cannot connect.
Show the code that does the Initialize and Connect.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Well, I've done some TCP socket programming in the past but haven't used the CAsyncSocket class. What is interesting for me is that listen() returns EWOULDBLOCK for you. listen() should never return EWOULDBLOCK if you take a look at its documentation. listen() is always blocking but only for a very short time, it either returns failure or does its job (establises incoming connection request queue, the backlog) and returns with success.
So whats wrong with your code? Here is my guess: After starting the listen you unnecessarily issue some other request on your listen socket (for example an accept() call) and that results in a WSAEWOULDBLOCK message that is not still not the end of the world, but strange and you should check out the reason for this. About the WSAEADDRINUSE problem: If your listening starts as expected then it allocates and uses a port on your machine. When you connect the client side should issue a connect() call that results in the following events: your server side receives an event and as a result calls accept(). Both the server side accept() call and the client side connect() call returns a socket that has random ports assigned. HOWEVER: If your misterious CAsyncSocket class calls bind() before the connect() call, then it will fix the port of the returned socket by the connect() call and if that is the same as the port on which your server is listening then the socket can not be created on the client side! You should make sure that bind isn't called before connect() allowing the connect() call to assign a random port for the client side socket! bind() is usually used before connect when your firewall allows only specific ports for the software to communicate.
Another side note: WSAEADDRINUSE might return if you shut down your program during debugging. In this case some of your sockets might stay alive inside the network subsystem because of lingering. In this case sometimes you have to wait for minutes for that socket object to diminish from the network subsystem so as to release your ports.
|
|
|
|
|
Oops. It is the Accept() that returns the would block WSA code, not Listen. My appologies.
Here are some code fragments:
Omitting the error checking and reporting, the server initialize does this
bool C_Server::Class_Initialize()
{ ...
m_winsock_status = AfxSocketInit();
...
m_winsock_status = Create( m_port_number, SOCK_STREAM,
FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
DEFAULT_IP_ADDRESS ); ...}
the Listen() method does this:
bool C_Server::Class_Listen()
{
m_winsock_status = Listen();
... }
And the Accept() looks like this:
bool C_Server::Class_Accept()
{
mp_C_Server_Send_Time_Socket = new C_Server_Send_Time_Socket;
m_winsock_status = Accept( *mp_C_Server_Send_Time_Socket );
...}
I have continued work and am partway through the Client code. The client initialize seems to be OK, the client Connect() gets WSA code 10035, socket in use. I am beginning to think that is to be expected.
Advice?
Thanks for your time
Edit, I keep messing with the formatting trying to get the code blocks to display correctly. Having some difficulties there. Preview looks good, but when I post it does not. I think I have it, disabled the checkbox to treat my content as plain text. But this darn edit box keeps jumping around in the text.
|
|
|
|
|
You say you have problems with connecting and you copy paste everything here except the client code and connect. First go and check whether you (or your CAsyncSocket class) issue a bind() call to the client socket before the connect call.
|
|
|
|
|
[QUOTE]First go and check whether you (or your CAsyncSocket class) issue a bind() call to the client socket before the connect call.[/QUOTE]
No it does not. So it should Call the Bind in the Client before the Connect?
Thanks for your time
Edit: What is the code to mark a quote?
Edit: according to an MSDN page, Create() calls socket and if sucessful calls Bind. If it calls Bind, why should I explicitly call bind.
http://msdn.microsoft.com/en-us/library/xz019029(v=vs.80).aspx[^]
|
|
|
|
|
No it shouldnt call bind because that could cause WSAEADDRINUSE as I described previously.
|
|
|
|
|
Well then, I think I was doing things out of order. My dialog has all the pieces broken out so I performed the following steps:
Server::Initialize, wsa = 0
Client::Initialize, wsa = 0
Server::Listen, wsa = 0
Client::Connect wsa = 10035
Client::OnConnect() is called
Server::OnAccept() is called
Client::OnSend() is called
As noted earlier, I have all those methods defined but with no body and a breakpoint in each. Is this normal behavior? If so,...
Does Client::OnConnect() need to do anything?
Same for Server::OnAccept and Client::OnSend?
I am getting close. Next Step?
Thanks for your time
Edit again: I have this code in the function C_Server::Class_Accept() that is called via a button in the dialog.
bool C_Server::Class_Accept()
{
mp_C_Server_Send_Time_Socket = new C_Server_Send_Time_Socket;
m_winsock_status = Accept( *mp_C_Server_Send_Time_Socket );
}
Now I that I see C_Server::OnAccept() called, that code should be moved into the OnAccept method and executed automatically after the client connects. Then I would NOT have a manually called Accept() method in the server class.
Does that sound right?
modified 16-Sep-12 20:16pm.
|
|
|
|
|
There are numerous versions of the basic copy function, too many now. some of the new versions are declared safer because they incorporate a limiting count value. However, all the ones I have tried and inadvertenly tested just crash the application. I find that rather rude.
Are there any versions of ...cpy...() and ...printf...() that limit the count of characters copied to the space found in the destination string. Without an ungracefull app crash?
Thanks for your time
|
|
|
|
|
bkelly13 wrote: Are there any versions of ...cpy...() and ...printf...() that limit the count of
characters copied to the space found in the destination string.
Without an ungracefull app crash?
Unfortunately, No. Strcpy and printf are two of the most common functions that hackers use to exploit programming errors to "hack" into a program. When using these functions you need to pay extra attention to the size of your memory buffers and the actions you are performing on them.
You may have better luck with the C++ Standard Library.
The std::string class will manage your memory buffers, copies and concatenations.
std::cout doesn't have the program crash issues that you are running into.
All of my software is powered by a single Watt.
|
|
|
|
|
In that case I wish to go on record as saying that we need a new set of these functions. These functions should be named ...strcpy_l(...) and ...printf_l(...), with the "l" (lower case L) standing for Limited. Under the covers, the function will examine the destination, determine the length of the destination, and quietly refuse to move more characters than the destination string can hold.
Thanks for your time
|
|
|
|
|
I misunderstood part of your question.
There are these two functions:
strncpy(pDest, pSrc, size)
and
snprintf(pDest, count, pFormatStr, ...)
These will do what you are asking. Read the descriptions though, strncpy will not NULL terminate your string if it can't write all of the data to the buffer. This would open yourself up to another set of possibilities to crash your program.
All of my software is powered by a single Watt.
|
|
|
|
|
Those sound like an improvement, but I claim both are defective. If they leave the string in an known improper state, then that is a serious problem.
Thanks for your time
|
|
|
|
|
I think both strncpy() and snprintf() sucks. Once I searched for hours for a bug that was caused by strncpy(). Here is the problem: strncpy() is suboptimal because even if you copy a 1 byte string, it fills the whole remaining part of the destination buffer with zeros unnecessarily, and on the other hand it doesn't zero terminate the string if its length equals to or bigger than the size of the dest buffer. The missing zero terminator character in similar cases is true for snprintf() too. I highly discourage everyone from using these functions.
|
|
|
|
|
bkelly13 wrote: In that case I wish to go on record as saying that we need a new set of these functions. It's no good making statements like this on CodeProject, you need to go and complain to the standards body.
One of these days I'm going to think of a really clever signature.
|
|
|
|