Archived

This forum has been archived. Please start a new discussion on GitHub.

can i create servant instance from shared library?help!

I tried to create servant instance from shared library like:

typedef Ice::Object* (*T_COMPONENT_FACTORY)();
...

IceInternal::DynamicLibraryPtr library
= new IceInternal::DynamicLibrary();
IceInternal::DynamicLibrary::symbol_type symbol
= library->loadEntryPoint(entryPoint, false);
T_COMPONENT_FACTORY factory = (T_COMPONENT_FACTORY)symbol;
Ice::ObjectPtr component = factory();

_adapter->add(component, Ice::stringToIdentity(identityStr));


but while the client calling the servant's method, it failed:

client:
.\TcpTransceiver.cpp:283: Ice::ConnectionLostException:
connection lost: WSAECONNRESET

server:
[ Service_D: Network: accepted tcp connection
local address = 10.10.10.75:10000
remote address = 10.10.10.75:2318 ]
Service_D: warning: connection exception:
.\ConnectionI.cpp:2133: Ice::UnknownException:
unknown exception:
unknown c++ exception
local address = 10.10.10.75:10000
remote address = 10.10.10.75:2318
[ Service_D: Network: closing tcp connection
local address = 10.10.10.75:10000
remote address = 10.10.10.75:2318 ]


can i do like this?! Thanks for your help!

Comments

  • matthew
    matthew NL, Canada
    lanbo wrote:
    I tried to create servant instance from shared library like:

    typedef Ice::Object* (*T_COMPONENT_FACTORY)();
    ...

    IceInternal::DynamicLibraryPtr library
    = new IceInternal::DynamicLibrary();
    IceInternal::DynamicLibrary::symbol_type symbol
    = library->loadEntryPoint(entryPoint, false);
    T_COMPONENT_FACTORY factory = (T_COMPONENT_FACTORY)symbol;
    Ice::ObjectPtr component = factory();

    _adapter->add(component, Ice::stringToIdentity(identityStr));


    but while the client calling the servant's method, it failed:

    client:
    .\TcpTransceiver.cpp:283: Ice::ConnectionLostException:
    connection lost: WSAECONNRESET

    server:
    [ Service_D: Network: accepted tcp connection
    local address = 10.10.10.75:10000
    remote address = 10.10.10.75:2318 ]
    Service_D: warning: connection exception:
    .\ConnectionI.cpp:2133: Ice::UnknownException:
    unknown exception:
    unknown c++ exception
    local address = 10.10.10.75:10000
    remote address = 10.10.10.75:2318
    [ Service_D: Network: closing tcp connection
    local address = 10.10.10.75:10000
    remote address = 10.10.10.75:2318 ]


    can i do like this?! Thanks for your help!


    It is certainly possible to do this, since this is essentially what IceBox does. The unknown c++ exception is most likely a translated structued exception (most likely an access violation). You can catch this easily enough in msdev. Go to Debug/Exceptions and then select Access Violation and select Action "Stop always". Then when your server dies you can determine what the problem is.

    If you want some hints on how to implement this I would suggest looking at the IceBox source and IceBox demo.

    Regards, Matthew
  • Thanks matthew!
  • There has a new problem :( , An unknown exception is thrown when the server running at this line(Incoming.cpp,line 175):

    status = _servant->__dispatch(*this, _current);

    What's the cause of the error?

    server's log:
    Service_D: warning: dispatch exception: unknown c++ exception
    identity: hello
    facet:
    operation: ice_isA
    [ Service_D: Network: closing tcp connection
    local address = 10.10.10.75:10000
    remote address = 10.10.10.75:4101 ]


    client's log:
    [ helloc: Network: tcp connection established
    local address = 10.10.10.75:4101
    remote address = 10.10.10.75:10000 ]
    .\Outgoing.cpp:398: Ice::UnknownException:
    unknown exception:
    unknown c++ exception
    [ helloc: Network: closing tcp connection
    local address = 10.10.10.75:4101
    remote address = 10.10.10.75:10000 ]

    Thanks for your help!
  • There are the debug values of the _servant's __vfptr:
    - __vfptr 0x0137f658 const THello::`vftable' *
    [0] 0x01371db0 THello::greet(const Ice::Current &) *
    [1] 0xfffffffc *
    [2] 0xfffffff0 *
    [3] 0xfffffffc *
    [4] 0x00000008 *
    [5] 0x00000014 *
    [6] 0x20646162 *
    [7] 0x74736163 *
    [8] 0x00000000 *
    [9] 0x65746e49 *
    [10] 0x636f6c72 *
    [11] 0x4564656b *
    [12] 0x61686378 *
    [13] 0x4165676e *
    [14] 0x26286464 *
    [15] 0x6665725f *

    They are differ from servant which is created and added to adapter in the static source code, such as:

    Ice::ObjectPtr component = new THello();
    _adapter->add(component, Ice::stringToIdentity(identityStr));

    Why???
  • benoit
    benoit Rennes, France
    I don't know why an unknown C++ exception would be raised from this code, it should work. The first thing you should do is to ensure that Ice, your DLL and executable are built with the same runtime library.

    If your DLL and exe are linked with the ice.lib import library, you should compile them with /MD (release multi threaded). If they are linked with iced.lib, you should compile them with /MDd (debug multi threaded).

    You could also take a look at the demo/IceBox/hello demo projects. I believe it's similar to what you're trying to do (the HelloI servant is compiled in the HelloService.dll and the DLL is loaded by the icebox executable).

    Benoit.
  • Thank benoit!

    In IceBox, servant is created within the "service library"(such as HelloService.dll) as static source code like(suppose HelloService have several servants, such as HelloServant1, HelloServant2...):

    --

    Ice::ObjectPtr component1 = new THelloServant1();
    _adapter->add(component1, Ice::stringToIdentity(identityStr1));

    Ice::ObjectPtr component2 = new THelloServant2();
    _adapter->add(component2, Ice::stringToIdentity(identityStr2));

    ...

    --

    Actually,I want to load "servant library" (such as HelloServant1.dll,HelloServant2.dll... but not HelloService.dll) in application process,which initialize service's Communicator and Adapter first.
  • matthew
    matthew NL, Canada
    lanbo wrote:
    Thank benoit!

    In IceBox, servant is created within the "service library"(such as HelloService.dll) as static source code like(suppose HelloService have several servants, such as HelloServant1, HelloServant2...):

    --

    Ice::ObjectPtr component1 = new THelloServant1();
    _adapter->add(component1, Ice::stringToIdentity(identityStr1));

    Ice::ObjectPtr component2 = new THelloServant2();
    _adapter->add(component2, Ice::stringToIdentity(identityStr2));

    ...

    --

    Actually,I want to load "servant library" (such as HelloServant1.dll,HelloServant2.dll... but not HelloService.dll) in application process,which initialize service's Communicator and Adapter first.

    The process is the same. If you need further assistance the best thing would be to create a self-contained compilable example that demonstrates the problem and we'd be glad to help.

    Regards, Matthew
  • matthew wrote:
    The process is the same. If you need further assistance the best thing would be to create a self-contained compilable example that demonstrates the problem and we'd be glad to help.

    Regards, Matthew

    The attachement is the whole example code, snippet from it:


    // Mode 1: Usually, we do like this.
    Ice::ObjectPtr hello1 = new THello();
    adapter->add(hello1, Ice::stringToIdentity("hello1"));

    IceInternal::DynamicLibraryPtr library
    = new IceInternal::DynamicLibrary();
    IceInternal::DynamicLibrary::symbol_type symbol
    = library->loadEntryPoint("hellos:createHello", false);
    T_COMPONENT_FACTORY factory = (T_COMPONENT_FACTORY)symbol;

    // Mode 2: I don't want to convert type obvious,
    // because I want it to be universal.
    Ice::ObjectPtr hello2 = dynamic_cast<IHello*>(factory());
    adapter->add(hello2, Ice::stringToIdentity("hello2"));

    // Mode 3: It is what I want, but it run unsuccessfully:(
    Ice::ObjectPtr hello3 = factory();
    adapter->add(hello3, Ice::stringToIdentity("hello3"));


    Thanks for your help!
  • matthew
    matthew NL, Canada
    lanbo wrote:
    The attachement is the whole example code, snippet from it:
    ........
    Thanks for your help!

    You need to change the definition of createHello to

    extern "C"
    {

    SCF_API Ice::Object* createHello()
    {
    return new THello;
    }

    }

    After I did this your example worked nicely.

    Best Regards, Matthew
  • Aha, It's OK now!

    A thousand thanks for Matthew's help!