View Single Post
  #3  
Old 01-16-2004, 11:58 AM
m0oni9
Hill Giant
 
Join Date: Dec 2003
Posts: 166
Default

Here is the process to set this stuff up in case anyone wants it. I was really posting more to the point to find out if anyone saw a problem with calling functions from perl this way. I only suggest it because from what I can tell, it's the best method. I'm also soliciting for any functions anyone might need to call from perl.

First, the code for the functions we will be calling from perl:
Code:
/* cperl.cpp */

#ifndef CPERL_CPP
#define CPERL_CPP

#ifdef EMBPERL

#include "masterentity.h"

extern Database database;

extern "C" {

  bool hasItem(unsigned charid, unsigned itemid)
  {
    Inventory inv;
    int ret = false;

    if (database.GetInventory(charid, &inv))
       if (inv.HasItem(itemid) != -1)
          ret = true;

    return ret;
  }

}


#endif // EMBPERL

#endif // CPERL_CPP
I also exported a new variable to export to perl, charid. This is around line 94 in embparser.cpp:
Code:
if (client && npc) {
                        fac = client->GetFactionLevel(client->GetID(), npcmob->GetID(), client->GetRace(), client->GetClass(), DEITY_AGNOSTIC, npc->GetPrimaryFaction(), npcmob);
                        ExportVar(packagename.c_str(), "charid", itoa(client->CharacterID()));
                }
Next, run make to compile the object file for cperl.cpp, and recreate the zone binary:

Now that we have our object code, we need to use XS to bring it and perl together. The following will create a work area for that:
Code:
h2xs -A -n Mytest
This will create a Mytest directory with a few skeleton files. We will now edit Mytest.xs. XS is a sort of language of its own. This is what my Mytest.xs file looks like:
Code:
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"

MODULE = Mytest         PACKAGE = Mytest

bool
hasItem(charid,itemid)
    INPUT:
        unsigned charid
        unsigned itemid
    CODE:
        RETVAL = hasItem(charid,itemid);
    OUTPUT:
        RETVAL
Now, run "perl Makefile.PL". This will create a new makefile.
Run "make". A file called Mytest.o will be generated, along with blib/lib/Mytest.pm. Copy the Mytest.pm file to your root Mytest directory.

We need to link Mytest.o and cperl.o together, so:
Code:
ld -shared `perl -MExtUtils::Embed -e ldopts` -o Mytest.so Mytest.o cperl.o
For good measure, I like to run "ld -shared -E Mytest.so" to see if there are unresolved symbols. The shared library should be created. Add the root Mytest directory to your perl INC path (ie: you can do this by setting the PERL5LIB environment variable). The perl script I tested this with is included in the first post. Go back to the eqemu directory and run world and zone. You should be able to log in, hail whoever you assigned the script to, and have the correct output.

edit: I forgot to note, make sure the new cperl.o (or whatever you call it) is put into the zone makefile so it gets compiled into the zone binary. Also, all of this does NOT need to be done to set it up on a server. Once the source from XS is created, that can be incorporated by itself (compiled and linked with the cperl.o file). This is just to quench any curiosity over this issue.
Reply With Quote