Archived

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

Link errors in linux

hi, there,
I want to migrate my windows application to linux . The application is built well in Win2K. I import the source codes into Eclipse in Enterprise linux 4 and build it with gcc.
Now I got a link error :

Building target: UTServer-Linux
Invoking: GCC C++ Linker
g++ -L/opt/Ice-3.0.0/lib -oUTServer-Linux ./IceGenerated/AutoDiscCommon.o ../IceGenerated/ServerCommon.o ./IceGenerated/ServerMap.o ./IceGenerated/DBTables/Event.o -lIce -lIceUtil -lFreeze
/usr/lib/gcc/i386-redhat-linux/3.4.3/../../../crt1.o(.text+0x18): In function `_start':
: undefined reference to `main'
collect2: ld returned 1 exit status

My application is a common Ice service ( daemon) derived from Service base class.


Thank you very much.



OrNot

Comments

  • bernard
    bernard Jupiter, FL
    The answer is in the error message: you need to define a main() function for your server, typically
    int main(int argc, char* argv[]) { ... }

    Maybe you have a WinMain() in your Windows app instead of main()?

    Bernard
  • hi, Bernard,

    I have the main function like any other ice service program.


    int
    main(int argc, char* argv[])
    {
    MyService srv;
    return svc.main(argc, argv);

    }
  • benoit
    benoit Rennes, France
    Hi,

    In which source file is this "main" function defined? You should include the object file for this source file in the linker command. From the linker command that you provided (below), you link with the AutoDiscCommon.o ServerCommon.o ServerMap.o, and Event.o object files. Is "main" defined in one of these objects?
    g++ -L/opt/Ice-3.0.0/lib -oUTServer-Linux ./IceGenerated/AutoDiscCommon.o ../IceGenerated/ServerCommon.o ./IceGenerated/ServerMap.o ./IceGenerated/DBTables/Event.o -lIce -lIceUtil -lFreeze

    Cheers,
    Benoit.
  • hi, Benoit
    Thanks for your reminder. You are right . The server.o is missed. I made a dir in eclipse CDT project named "head files" just for convenience and added this dir in the include list . Unfortunately, it seems that gcc( or eclipse?) does not permit -IincludePath with space and did not complie the server.cpp for me. But I am so stupid to assume it as a matter of course .
    Now I changed "head files" to "head-files" and everything is OK now.

    Thanks a lot .

    OrNot
  • But what if we have a winMain application?

    Hello,

    We actually do have a winMain() instead of a main() in one of our applications and are having a lot of trouble in that the application actually breaks when we try to create an adapter. We are trying to use IceGrid. How should the server look with this winmain? We are using c++ and Ice 3.2 BTW.

    Many thanks.
  • bernard
    bernard Jupiter, FL
    Ice does not care about the kind of "main" function used by your program. Without additional information, it's hard to guess your problem.

    Do you link with the proper runtime library (/MD with ice.lib and iceutil.lib or /MDd with iceD.lib and iceutilD.lib)?

    Do you build with the proper flags, e.g. with RTTI enabled?

    Best regards,
    Bernard
  • Thanks for your quick reply Bernard,

    Yes everything is set fine. We had everything running fine with direct proxies and are trying to get the applications to run with IceGrid now.

    We have three applications. A is a client, B is a server (and a client to C). All the connections except for the ones between B and C are now running fine with IceGrid.

    Application C is a windowed application (a simulation running in a window) with a WinMain. This winmain creates an app of a class necessary for the simulation. It calls a function that starts setting things up for the simulation. What we did was to let it go ahead and call this setup function and there, we call create an instance of the server class we created for the Ice server, with a run, etc.. but have no idea how to initialize argc and argv to pass it to server.main... All the class really does is save the communicator to a private variable. Back in the setup function, we get this variable with an implemented getCommunicator function within the server class. This communicator is then passed to the necessary classes where the actual creation of the adapters take place.

    The code should be ok.. we've done it so many times and think we have it quite ok. Starting the client (A) starts B and C too, but B gets an error - no suitable endpoints when it tries to connect to C.

    This sounds horrible to read - I hope its somewhat clear. Thanks for your time! Any help would be much appreciated!
  • xdm
    xdm La Coruña, Spain
    to figure why B can't connect C try to enable Ice.Trace.Network=3 on B a view if is connecting to the correct endpoints.

    Respet to argc , argv you can create a dummy params.

    i think this should work
    int argc=0
    char** argv=0;
    server.main(argc,argv)
    
  • benoit
    benoit Rennes, France
    Hi,

    Does A directly connect to C and is it able to establish a connection with C?

    It sounds like you're getting an Ice::NoEndpointException exception when trying to invoke on C from B. Often, this occurs when the IceGrid locator can't figure out the endpoints of an indirect adapter because the server couldn't be started succesfully. You should try to run your IceGrid node with the properties IceGrid.Node.Trace.Activator=2 and IceGrid.Node.Trace.Adapter=2, this should give you some hints.

    Also, you should make sure that the communicator initialized in C is properly configured. If it's started by the IceGrid node you need to make sure that it correctly reads the configuration file provided by the node with the --Ice.Config command line argument. Therefore you most likely need to pass valid argc/argv arguments to your main method. You should be able to extract the argc/argv parameters from the command line argument of the WinMain method, see this link for more information.

    Cheers,
    Benoit.
  • Thanks!

    It was indeed the case the communicator wasn't being configured as it wasn't using the command line arguments. ( The link you sent was very helpful: CommandLineToArgvW() then wcstombs() ). I'm passing those now and it seems ok. (but not in the backwards direction - meaning: we see that the adapters are created and activated, and the commands flow from A to B to C but nothing is getting back from C to B to A.) We're confident about the connections from A to B and back.. the issue must be from C to B.

    I have another question though: Does it matter that we create the adapters and activate them in server.run, or should it be ok to just save the communicator and pass it to the classes where the adapters are needed and create them there? Another issue was threading... when we first built the simulator, we had a thread running for the tcp/ip connection - just listening, etc so the whole application doesn't block. Is this still needed? Intuitively, it doesn't seem like it.. but we're just not sure now. When we were using the dircet proxies, we still created them in threads (each adapter in its own thread)... bit confused..


    Thanks again!
  • benoit
    benoit Rennes, France
    Hi,

    You don't have to create the adapters in run(), you can create them at any time from your own classes. Ice::Application is really just a convenience class that create the communicator for you and handles console interrupts (Ctrl-C). You are not required to use it (see demo/Ice/minimal for a demo which isn't using it).

    Also, you can create and activate adapters from a non-dedicated thread. Once activated the adapter will handle incoming connections and requests thanks to the Ice server thread pool (see the Ice manual for more information).

    Cheers,
    Benoit.
  • Thank you very much for all your help! It all runs beautifully! We followed the minimal example and simply have the main function in the server class return the pointer to the communicator. Thanks again :)