Home Help Center

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

  • matthewmatthew NL, CanadaMember Matthew NewhookOrganization: ZeroC, Inc.Project: Internet Communications Engine ✭✭✭
    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
  • lanbolanbo Member
    Thanks matthew!
  • lanbolanbo Member
    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!
  • lanbolanbo Member
    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???
  • benoitbenoit Rennes, FranceAdministrators, ZeroC Staff Benoit FoucherOrganization: ZeroC, Inc.Project: Ice ZeroC Staff
    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.
  • lanbolanbo Member
    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.
  • matthewmatthew NL, CanadaMember Matthew NewhookOrganization: ZeroC, Inc.Project: Internet Communications Engine ✭✭✭
    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
  • lanbolanbo Member
    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!
  • matthewmatthew NL, CanadaMember Matthew NewhookOrganization: ZeroC, Inc.Project: Internet Communications Engine ✭✭✭
    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
  • lanbolanbo Member
    Aha, It's OK now!

    A thousand thanks for Matthew's help!
Sign In or Register to comment.