Go Back   ZeroC Forums > Help Center

Reply
 
LinkBack Thread Tools Rate Thread Display Modes
  #1 (permalink)  
Old 08-06-2003
amrufon's Avatar
amrufon amrufon is offline
Registered User
 
Name: Alex
Organization: IST
Project: jDatabase
 
Join Date: May 2003
Location: Manila, Philippines
Posts: 96
Send a message via Yahoo to amrufon
-->
Unhappy Access Violation using ICE with Automation DLL

Hello.

Backgrounder first. I'm a VB programmer who's trying out ICE with VB so that I can integrate it with our applications. You can categorize me as a newbie with regards to C++. Also, this post is in connection with Using ICE with Single Threaded DLL post.

Ok, now with the problem:
1.) I created a VB ActiveX DLL which only has one interface. A function wich accepts a string and returns a string. Pretty simple.
2.) I made the following slice definition to support the DLL.
Quote:
interface jSockets
{
string jclCommand(string command);
};
3.) I then proceeded to make a client and a server classes to manage the connection. Here is a code snippit on the server:
jSocketsI.h
Quote:
#include <jSockets.h>
#include <IceUtil/Mutex.h>

#define INITGUID
#import "..\jIceServer\bin\jIceServer.dll"
#include "icrsint.h"

using namespace jIceServer;

class jSocketsI : public jSockets {
public:
virtual ::std::string jclCommand(const ::std::string& command, const Ice::Current&);
jSocketsI();
~jSocketsI();
private:
bool initialize();
_jServerPtr pjServer;
IceUtil::Mutex _jServerMutex;
};
jSockets.cpp
Quote:
#include "stdafx.h"
#include "jSocketsI.h"

using namespace std;

std::string jSocketsI::jclCommand(const ::std::string& command, const Ice::Current&) {
// Make sure that were thread safe
IceUtil::Mutex::Lock lock(_jServerMutex);

// Declare used variables
std::string retval;
_bstr_t data = command.c_str();

// Call the J Object and get the return parameter
retval = pjServer->jclCommand(data);

// Return the values
return retval;
}

bool jSocketsI::initialize() {
// Make sure that were thread safe
IceUtil::Mutex::Lock lock(_jServerMutex);

// Make sure that were connected
CoInitialize(NULL);
pjServer.CreateInstance(__uuidof(jServer));

// Return that all is well
return true;
}

jSocketsI::jSocketsI() {
// Initialize the COM environment, this
// extra call ensures that the Adapter Class will
// not go out of scope.
initialize();
}

jSocketsI::~jSocketsI() {
CoUninitialize();
Just for completeness, here's the code for the main application
IceServer.cpp
Quote:
#include <Ice/Ice.h>
#include <jSocketsI.h>

using namespace std;

class IceServer : virtual public Ice::Application {
public:
virtual int run(int, char* []) {
// Server code
Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapterWithEndpoints("jclCommandAdapt er", "default -p 7012");
Ice::ObjectPtr object = new jSocketsI;
adapter->add(object, Ice::stringToIdentity("jclCommand"));
adapter->activate();

// Wait until all operations are completed
communicator()->waitForShutdown();
if (interrupted()) {
cerr << appName() << ": received signal, shutting down" << endl;
}
return 0;
};
};

int main(int argc, char* argv[]) {
IceServer app;
return app.main(argc,argv);
}
This code will actually compile and run but the problem is that when the clients connects and actually calls the "jclCommand", it will fail with an access violation in the code:
Quote:
// Call the J Object and get the return parameter
retval = pjServer->jclCommand(data);
I don't know what to do anymore. I'm close to just giving up and walking away.

Any help?

Thanks.

Alex
Reply With Quote
  #2 (permalink)  
Old 08-06-2003
marc's Avatar
marc marc is offline
ZeroC Staff
 
Name: Marc Laukien
Organization: ZeroC, Inc.
Project: The Internet Communications Engine
 
Join Date: Feb 2003
Location: Florida
Posts: 1,780
I'm afraid from the code fragments alone, it's not possible to say what is going on. I can't see anything obvious wrong. We would need to see a complete and compilable example, since we don't know what's going on in jclCommand().
Reply With Quote
  #3 (permalink)  
Old 08-06-2003
amrufon's Avatar
amrufon amrufon is offline
Registered User
 
Name: Alex
Organization: IST
Project: jDatabase
 
Join Date: May 2003
Location: Manila, Philippines
Posts: 96
Send a message via Yahoo to amrufon
-->
Hello Marc,

Its a good thing you replied to this post and said that everything looks Ok. Because when I was trying to trim down the VB code so I can post it here ... I thought of a solution which worked!!!

Ok, first off, what I was trying to do was something like this:
Quote:
ice client -->> internet --> ice server -->> vb dll --> proprietary COM libraries
What I was doing from the code above is that the IceServer is creating an instance of the vb dll when it initializes. If you would recall your documentation on Chapter 14: Threads and Concurrency with C++, you guys kept pointing out that ICE is a multi-threaded system. So from my own testing, it seems that each calls made by the client to the server is given its own thread. So the Access Violation occurs when the newly created thread for the client is trying to access the variable initialized by the main application thread:

The pjServer was initialized by the Main Application
Quote:
bool jSocketsI::initialize() {
// Make sure that were thread safe
IceUtil::Mutex::Lock lock(_jServerMutex);

// Make sure that were connected
CoInitialize(NULL);
pjServer.CreateInstance(__uuidof(jServer));

// Return that all is well
return true;
}

jSocketsI::jSocketsI() {
// Initialize the COM environment, this
// extra call ensures that the Adapter Class will
// not go out of scope.
initialize();
}
and was access by the new thread here ... where it fails
Quote:
std::string jSocketsI::jclCommand(const ::std::string& command, const Ice::Current&) {
// Make sure that were thread safe
IceUtil::Mutex::Lock lock(_jServerMutex);

// Declare used variables
std::string retval;
_bstr_t data = command.c_str();

// Call the J Object and get the return parameter
retval = pjServer->jclCommand(data);

// Return the values
return retval;
}
My Solution
So my solution was to modify my VB DLL from an ActiveX Apartment Threaded DLL to an ActiveX EXE library (please refer to the attached image on how I configured the VB project for this). Then I modified the my Ice Adapter in such a way that each new call made by the client will create a new instance of the ActiveX EXE library. Here's the change codes:

jSocketsI.h
Quote:
#include <jSockets.h>
#include <IceUtil/Mutex.h>

#define INITGUID
#import "..\jIceServer\bin\jIceServer.exe"
#include "icrsint.h"

using namespace jIceServer;

class jSocketsI : public jSockets {
public:
virtual ::std::string jclCommand(const ::std::string& command, const Ice::Current&);
jSocketsI();
~jSocketsI();
private:
_jServerPtr pjServer;
IceUtil::Mutex _jServerMutex;
};
jSocketsI.cpp
Quote:
#include "stdafx.h"
#include "jSocketsI.h"

using namespace std;

std::string jSocketsI::jclCommand(const ::std::string& command, const Ice::Current&) {
// Make sure that were thread safe
IceUtil::Mutex::Lock lock(_jServerMutex);

// Declare used variables
std::string retval;
_bstr_t data = command.c_str();
_bstr_t temp;
_jServerPtr lpjServer;

// Make a new connection to the J Server ONLY for this thread
CoInitialize(NULL);
lpjServer.CreateInstance(__uuidof(jServer));

// Call the J Object and get the return parameter
temp = lpjServer->jclCommand(data);
retval = temp;

// Uninitalize the COM Automation for this thread
CoUninitialize();

// Return the values
return retval;
}

jSocketsI::jSocketsI() {
// Initialize the COM environment, this call
// ensures that an instance of J will be running
// until this application quit
CoInitialize(NULL);
pjServer.CreateInstance(__uuidof(jServer));
}

jSocketsI::~jSocketsI() {
CoUninitialize();
}
So, if you would look closely in the jSocketsI::jclCommand function, I create a local variable called lpjServer that is initialized and closed at that function level.

Summary
As I say, this works. Unfortunately, I'm not satisfied with my solutions. Let me put it this way: To get into a living room of a house, all you need to do is walk up to the door and go in. What I just did was make my own ladder, climb up to the second floor, crawl through the window and go down the stairs just to get to the living room.

Although, because of time constraints, I'll have to stick with my current solution (until a better one comes up) and move to making an IceClient DLL that can be called by our proprietary libraries. I was wondering if anybody has insights, thought and/or ideas on this issue of mine. Also, did I really understand how ICE works or I'm just fooling myself?

Thanks.

Alex
Attached Thumbnails
access-violation-using-ice-automation-dll-jiceserver.jpg  

Last edited by amrufon : 08-06-2003 at 11:18 PM.
Reply With Quote
Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

Similar Threads
Thread Thread Starter Forum Replies Last Post
Can I Simultenously Access an ICE server alexm Help Center 1 11-17-2006 03:19 AM
DLL access violation youkind Help Center 2 08-15-2006 04:47 AM
How to get access to marshaled/demarshaled data andreynech Help Center 2 06-14-2005 06:48 AM
service access control problem yomi Help Center 7 04-04-2004 10:36 AM
Self access problem Jonathan Help Center 2 03-31-2004 06:40 AM


All times are GMT -4. The time now is 12:38 PM.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.0.0
(c) 2008 ZeroC, Inc.