Crystal Space
Welcome, Guest. Please login or register.
July 30, 2014, 08:05:30 am

Login with username, password and session length
Search:     Advanced search
9009 Posts in 2047 Topics by 8259 Members
Latest Member: Robinfallon
* Home Help Search Login Register
+  Crystal Space
|-+  Associate Projects
| |-+  CEL Discussion
| | |-+  Loading map with CEL fails (zonemanager)
« previous next »
Pages: [1] 2 Print
Author Topic: Loading map with CEL fails (zonemanager)  (Read 8220 times)
mark
Full Member
***
Posts: 101


View Profile
« on: September 18, 2005, 12:21:51 pm »

I am trying to load a mapfile with CEL as described in the celtut chapter 3. I'm using an own class for this:

Code:
Maploader::Maploader(csRef<iObjectRegistry> objectRegistry) {
    this->obreg = objectRegistry;
    this->pl = CS_QUERY_REGISTRY (objectRegistry, iCelPlLayer);
    this->vfs = CS_QUERY_REGISTRY (objectRegistry, iVFS);
    this->mapEntity = NULL;

    if (!pl->LoadPropertyClassFactory ("cel.pcfactory.zonemanager")) {
        csPrintfErr("ZONEMANAGER!\n");
    }
}

bool Maploader::loadMap(csString map) {
    vfs->ChDir("/maps.zip");
    mapEntity = pl->CreateEntity (map, 0, 0, "pczonemanager", 0);
    if (!mapEntity) {
        csPrintf(csString(gettext("map_load_error"))+map+"!\n");
        return false;
    }

    csRef<iPcZoneManager> zonemgr = CEL_QUERY_PROPCLASS_ENT (mapEntity,iPcZoneManager);
    iCelZone* zone = zonemgr->CreateZone ("main");
    iCelRegion* region = zonemgr->CreateRegion ("main");
    zone->LinkRegion (region);
    iCelMapFile* mapfile = region->CreateMapFile ();

    mapfile->SetPath (map);
    mapfile->SetFile (map);
    return true;

the line "csRef<iPcZoneManager> zonemgr = CEL_QUERY_PROPCLASS_ENT (mapEntity,iPcZoneManager);" segfaults, but everything before is ok: mapEntity is created, no errormessages appear.

Why can't the zonemanager be queried? I don't understand...

Backtrace is
Code:
#0  0xb7e15231 in scfInterfaceTraits<iPcZoneManager>::GetID () at zone.h:201
#1  0xb7e1516b in celQueryPropertyClass<iPcZoneManager> (plist=0x8220ee0)
    at propclas.h:496
#2  0xb7e14fe6 in celQueryPropertyClassEntity<iPcZoneManager> (
    entity=0x8220ed0) at propclas.h:518
#3  0xb7e1445f in Maploader::loadMap (this=0x821fbb0, map=
        {<csStringFast<36>> = {<csStringBase> = {_vptr.csStringBase = 0x80ae668, Data = 0x0, Size = 5, MaxSize = 0, GrowBy = 64}, minibuff = "world\000\000\000�f\"\b\000\000\000\000\b�f\b�$�004\bh!\b\200�n\b", miniused = 6}, <No data fields>}) at Maploader.cpp:45
Logged

Gentoo Linux ~x86, kernel 2.6.11-cko9 smp, gcc 3.4.4-r1, binutils 2.16.1, glibc 2.3.5 NPTL
CS+CEL Pseudo Stable 2005.09.03
jorrit
Administrator
Hero Member
*****
Posts: 1706


View Profile
« Reply #1 on: September 18, 2005, 01:22:34 pm »

Hmm... don't have an explanation for that. Perhaps something more fundamental is wrong in your app. If you are on linux you could use valgrind memory debugger. Otherwise I'm afraid I have no clue. The code looks ok to me :-/

One other tip. Try a clean build of CS+CEL+your app to be sure that that is ok.

Greetings,
Logged
mark
Full Member
***
Posts: 101


View Profile
« Reply #2 on: September 18, 2005, 07:35:07 pm »

A clean build doesn't help and valgrind doesn't bring useful information or errors.
So let's check what I need/have:

Requests and Queries for Engine, VFS, Null3d, Imageloader, Levelloader, Reporter, ~listener, PlLayer, BlLayer.Test (not in use yet (and will be replaced), but registered with Physlayer).
Now I'm mounting my mapfiles etc; they are found.
Now I create the maploader which (see code above) and then I load a specified mapfile.

Is something missing? Can it fail because something is wrong with the mapfile or textures are missing or something like that?

The last thing in the backtrace is "scfInterfaceTraits<iPcZoneManager>::GetID ()"
Maybe the error is outside my code?
Logged

Gentoo Linux ~x86, kernel 2.6.11-cko9 smp, gcc 3.4.4-r1, binutils 2.16.1, glibc 2.3.5 NPTL
CS+CEL Pseudo Stable 2005.09.03
jorrit
Administrator
Hero Member
*****
Posts: 1706


View Profile
« Reply #3 on: September 19, 2005, 05:28:40 am »

Can you try to examine in gdb why exactly is it crashing? What is it trying to do? Deref or a null pointer or what?

Greetings,
Logged
mark
Full Member
***
Posts: 101


View Profile
« Reply #4 on: September 19, 2005, 08:39:01 am »

ok, I'll step through the code:
new Maploader() is not NULL (that's that's asserted too)

entering loadMap():
vfs->ChDir is ok (it's mounted as maps.zip in workdir+"$/share$/maps.zip", GetMounts() lists it as "/maps.zip/" and it's found. The file includes only one mapfile, with the filename "world". the loadMap-parameter csString map is "world")
mapEntity is not NULL after CreateEntity
method calls from CEL_QUERY_PROPCLASS_ENT (mapEntity,iPcZoneManager):
-> celQueryPropertyClassEntity(iCelEntity*)           (propclas.h, 518)
-> celQueryPropertyClass(iCelPropertyClassList*)
-> FindByInterface(GetID(), GetVersion())                (propclas.h, 496)
-> SCF_VERSION(iPcZoneManager, 0, 1, 1);         (zone.h, 201 -- entered by scfInterfaceTraits<iPcZoneManager>::GetID())
-> segfault

Assemblercode for SCF_VERSION(iPcZoneManager, 0, 1, 1):
push %ebp                        (step ok)
mov %esp, %ebp             (step ok)
push %ebx                         (step ok)
sub $0x14, %esp              (step ok)
call 0xb7e25564 <__i686.get_pc_thunk.bx>           (step ok)
add $0x34630, %ebx                (step ok)
-> back to SCF_VERSION(iPcZoneManager, 0, 1, 1) -> next step segfault

(This is what the backtrace from above says too, I can't find out more - or at least I don't know if/how I can find out more *g*)
« Last Edit: September 19, 2005, 08:42:52 am by mark » Logged

Gentoo Linux ~x86, kernel 2.6.11-cko9 smp, gcc 3.4.4-r1, binutils 2.16.1, glibc 2.3.5 NPTL
CS+CEL Pseudo Stable 2005.09.03
sunshine
Administrator
Sr. Member
*****
Posts: 294


View Profile
« Reply #5 on: September 19, 2005, 10:50:58 am »

scfInterfaceTraits<>::GetID() has a few prerequisites. Perhaps one of them is not being met. It expects that the global iSCF::SCF variable has been initialized properly. It also expects that csStaticVarCleanup() can be invoked safely.
Logged
mark
Full Member
***
Posts: 101


View Profile
« Reply #6 on: September 19, 2005, 11:33:35 am »

hm, the Maploader-class is outside my main-application (and doesn't even know the mainapp, I just give the objectRegistry to it), maybe that's the cause that these prerequisites are not met.
But what do I have to do to give access to csStaticVarCleanup and SCF so that GetID() works?
Logged

Gentoo Linux ~x86, kernel 2.6.11-cko9 smp, gcc 3.4.4-r1, binutils 2.16.1, glibc 2.3.5 NPTL
CS+CEL Pseudo Stable 2005.09.03
sunshine
Administrator
Sr. Member
*****
Posts: 294


View Profile
« Reply #7 on: September 19, 2005, 03:18:54 pm »

I assume that you've used the CS_IMPLEMENT_APPLICATION macro in your main .cpp file? Typically, this should be all that's needed for the 'static var cleanup' stuff.
Logged
mark
Full Member
***
Posts: 101


View Profile
« Reply #8 on: September 19, 2005, 06:00:15 pm »

Yes, I use that in my main-app.
The Maploader is inside a shared library though. There I use CS_IMPLEMENT_FOREIGN_DLL.
Logged

Gentoo Linux ~x86, kernel 2.6.11-cko9 smp, gcc 3.4.4-r1, binutils 2.16.1, glibc 2.3.5 NPTL
CS+CEL Pseudo Stable 2005.09.03
jorrit
Administrator
Hero Member
*****
Posts: 1706


View Profile
« Reply #9 on: September 19, 2005, 06:09:44 pm »

Yes, I use that in my main-app.
The Maploader is inside a shared library though. There I use CS_IMPLEMENT_FOREIGN_DLL.

Aha. It is possible that the problem is related to that. I hope Eric can tell exactly what the solution is there.

Greetings,
Logged
sunshine
Administrator
Sr. Member
*****
Posts: 294


View Profile
« Reply #10 on: September 19, 2005, 06:46:48 pm »

In that case, the problem is almost certainly that you did not initialize the global iSCF::SCF variable in your shared library. iSCF::SCF gets initialized automagically for CS applications and for CS plugins, but not for foreign shared libraries. For those, you must initialize it manually. To fix, you need to pass a pointer to the singleton iSCF instance into your shared library when you initialize it, and make sure that your library's initialization function sets iSCF::SCF to the passed in value. (This may be the same function into which you pass the singleton iObjectRegistry.)

To obtain the singleton iSCF instance, just grab it from the iSCF::SCF variable of some module which already has that value, such as the application (if it is loading your shared library) or from a CS plugin (if it is loading your shared library).
Logged
mark
Full Member
***
Posts: 101


View Profile
« Reply #11 on: September 19, 2005, 09:54:30 pm »

HEUREKA! That's it. I appended an initialize function to my lib, that calls csInitializer::InitializeSCF(argc, argv) and call that function in Application(). Now it works.
1000 Thanks, that is better than Asperin Cheesy
Logged

Gentoo Linux ~x86, kernel 2.6.11-cko9 smp, gcc 3.4.4-r1, binutils 2.16.1, glibc 2.3.5 NPTL
CS+CEL Pseudo Stable 2005.09.03
sunshine
Administrator
Sr. Member
*****
Posts: 294


View Profile
« Reply #12 on: September 20, 2005, 01:20:19 pm »

If your main application has already called csInitializer::InitializeSCF() or CreateEnvironment(), or whatnot, it is more correct for you simply to pass the iSCF::SCF pointer from your application into your shared library and have your shared library manually set its iSCF::SCF pointer from that value. Calling csInitializer::InitializeSCF() from within your shared library is not the correct solution since it almost certainly causes a second instance of csSCF to be created (and this class should only ever be instantiated a single time). On the other hand, if no other entity has called csInitializer::InitializeSCF() prior to your shared library being initialized, then invoking csInitializer::InitializeSCF() is appropriate.
Logged
mark
Full Member
***
Posts: 101


View Profile
« Reply #13 on: September 20, 2005, 02:26:02 pm »

hm, but how do I pass it to the library or use it there?
If I store a global pointer in my lib, how does the zonemanager know that it must use this pointer as SCF replacement (even though it may point to SCF)?
And creating the pointer with the name "SCF" produces a compile error because the name is already in use. (or do I need a namespace for that?)
Logged

Gentoo Linux ~x86, kernel 2.6.11-cko9 smp, gcc 3.4.4-r1, binutils 2.16.1, glibc 2.3.5 NPTL
CS+CEL Pseudo Stable 2005.09.03
sunshine
Administrator
Sr. Member
*****
Posts: 294


View Profile
« Reply #14 on: September 20, 2005, 04:53:11 pm »

The iSCF::SCF variable is already declared when you #include <scf.h>. You just pass the existing SCF pointer from your application into your shared library when you load your library and then set iSCF::SCF. For instance:

void my_library_init(iSCF* scf, iObjectRegistry* reg)
{
  iSCF::SCF = scf;
  whatever = reg;
}

In your main application (or whatever entity is responsible for loading your shared library:

libref = load_my_library('foobar');
libref->my_library_init(iSCF::SCF, reg);
Logged
Pages: [1] 2 Print 
« previous next »
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.2 | SMF © 2006-2007, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Page created in 4.171 seconds with 14 queries.