Jump to content

[SOLVED] issue with dynamically loading c++ created extension in php.ini


logansama

Recommended Posts

Good day,

 

Attempting the way of dynamically loading a created extension (.so) via the php.ini on linux.

The extension is a c++ based extension created using Swig framework.

 

I understand the php.ini way being: (for explaining purposes 'extension.so' represents the extension file/s )

1. copy the extension.so file to be used, to the extensions dir/location specified by the the php.ini file

2. add to the php.ini file (under Dynamic Extensions) the line "extension=extension.so"

3. Restart the apache to reload the new settings of the php.ini.

4. Call the functions in a php file to test.

 

unfortunately i receive errors when calling the function:

"Fatal error: Call to undefined function foo() in /file_location/file.php on line #"

 

when testing by adding the following code to top of php file....:

(please note that enable_dl is On in the php.ini)

if( dl('extension.so') ) {
        echo "could load all good! <br>";
}

..i recieve the output:

""Warning: Module 'extension' already loaded in Unknown on line 0""

i understand the above to mean that dl is trying to load something that is already loaded.

i also did a command line check 'php -m' to check that the 'test' extension i am dynamically loading has not been compiled in with php. And it has not been.

 

I am not sure if this all means the extension has loaded correctly but its been created incorrectly, or if the shared object has just not been loaded correctly.

 

If anyone knows that my php.ini implementation is flawed, please tell me and if possible also on how to do it correctly.

If you know of another way to do dynamically add extension library files, please help me out.

 

I thank you in advance.

Link to comment
Share on other sites

i understand the above to mean that dl is trying to load something that is already loaded.

 

That is indeed correct, so it would appear your extension loads.

 

i also did a command line check 'php -m' to check that the 'test' extension i am dynamically loading has not been compiled in with php. And it has not been.

 

The php cli is a completely different engine to that of mod_php. Are all these test happening via the cli?

 

Maybe there is a fault in the extension itself? Does foo() actually exist? (Silly question I'm sure)

Link to comment
Share on other sites

by all means i am sure that the extension has not been configured as part of php.

 

I am not sure if the extension shared-object does contain a fault. Is there a means to test it?

The shared object is created by compiling a wrapped .cpp file. This wrapped .cpp file is created by Swig using a normal .cpp file with c++ code. This wrapped cpp file contains the needed php/zend/cpp/c converted code used by php to understand extension. The original cpp file has the function foo(), the wrapped cpp file (before compiling) has the function as _wrap_foo() and the EXAMPLE php file the Swig created (to test the shared object extension) has a call to _foo().

 

In my test php file i have made a call to foo(), _wrap_foo() and _foo() and all of them result in "call to undefined function". I am now trying to figure out what the extension contains, wonder if there is a standard way to view the content of a loaded extension?

Link to comment
Share on other sites

You could look at its exports in a debugger or something.

 

So, how exactly does the C wrapper work?  (I'm guessing the wrapper is written in C and is around a C++ class.)  Is the C++ code compiled into a lib and then the wrapper compiles it in and makes calls with the right calling type or something?  What exactly is the wrapper doing?

Link to comment
Share on other sites

Swig does the 'wrapping' of  your source/implementation code before you proceed to compile it into a shared object. Normal extensions are in C so you need some extra conversion if you are using C++. Swig apparently does all the needed changes for you. I just need to figure out exactly how so i can actually use the extension. A link if you want more detail http://www.swig.org/Doc1.3/Php.html#Php_nn2_6

 

it also deals with many other langiages, not just php and c++.

 

 

Link to comment
Share on other sites

Some additional findings: (and with these i find myself in waters i have not swam in before. )

 

ran "php --re test" ('test' being the name of the extension i created using the Swig environment):

Extension [ <persistent> extension #55 test version <no_version> ] {

 

  - Functions {

    Function [ <internal:test> function new_test ] {

    }

    Function [ <internal:test> function test_calc ] {

    }

    Function [ <internal:test> function test_getnumber ] {

    }

  }

}

 

 

test_calc is implemented in the original cpp file to receive two int parameters.

so when i call itin a php file as follows:

<?PHP

test_calc(10,10);

 

i get the following:

Warning: Wrong parameter count for test_getnumber() in /opt/lampp/htdocs/extension/calculate.php on line 6

 

the test_getnumber() is supposed to receive no parameters but when i call test_getnumber() i get the same warning as above.

 

At this point i am not even sure what to ask help for? hehe :)

I think i will settle for ANY input or opinions etc.

 

Thank you.

Link to comment
Share on other sites

Last night i managed to get something going. Its basic, maybe not exactly 100% correct, but it works and is a good starting point. Please note that i still created the extension using Swig. Also note that the C++ i used was based on tutorial examples i could find, i am not a c++ programmer. :)

 

To provide the data and steps:

1.) The Input file :: test4.i

%module test4

%{
#include "test4.cpp"
%}
%include "test4.cpp"

This file describes what you want to include. I always had the file.h descriptions here, but that caused a fault when a function was called from the php. The reason was that the function is listed in the extension but the implementation does not exist. By listing the cpp file (implementation) the function calls result correctly in the php.

 

2.) test4.h

#ifndef __TEST4_H__
#define __TEST4_H__

int test4_showNumber();

#endif

 

3.) test4.cpp

#include <iostream>
#include "test4.h"

using namespace std;

int test4_showNumber()
{
    int num = 8 +12;
    return num;
}

Please note this is VERY simple, the point was just to test actual implementation.

 

I did everything in Ubuntu 8.10. In order to use swig you need to have it installed. View their website for more details on everything they do. http://www.swig.org. You also need a working PHP installed. I used XAMPP for linux (lampp) as well as a version compiled from source. v5.2.8 PHP in both cases. And lastly a working gcc/g++ installation. I used version 4.3.2.

 

In the directory where the three above files are located i ran the following commands:

1.)

swig -php5 -c++ test4.i

this builds a few files. Their uses can be read about on their site.

 

2.)

g++ 'php-config --includes' -fpic -c test4_wrap.cpp

Please note that i did not type 'php-config --includes' as part of the command. What i mean by it is that the output you get from the command 'php-config --includes' should be added in the command above in its place. The lampp installation did not have the needed include directories and files, so i used those from the source built php.

 

3.)

g++ -shared test4_wrap.o -o test4.so 

Then copy the .so file to where your extensions are stored. In my case with lampp it was in ../lampp/lib/php/extension/no-debug-non-zts-20060613/.

Then edit your php.ini file: Add the following under "Dynamic Extensions":

extension=test4.so

 

Then restart your apache so that the new settings of the php.ini is loaded.

 

The test php file i created was as follows:

<?PHP

if( extension_loaded("test4") ) {
        echo "<br><br><br>LOADED TEST 4 !! <br>";
}
else {
        echo "NOTHING!! <br>";
}

if (function_exists('test4_showNumber')) {
    echo "test4_showNumber is available.<br />\n";
} else {
    echo "test2_testNumber not available.<br />\n";
}

echo "<br>The number is ....<br>";
$val1= test4_showNumber();
echo $val1;

 

the output is then:

 

LOADED TEST 4 !!

test4_showNumber is available.

The number is ....

20

 

Like i said a very simple implementation, but still an implementation and a start.

Thank you for all the help everybody and hope someone finds this helpful/interesting.

 

 

Link to comment
Share on other sites

Glad you got it figured out ;p.

 

 

Just wondering, are you writing an extension from scratch, or are you using some pre-written library of yours or something?  If you're writing from scratch, it might just be easier to write it in C.  That code up there was entirely valid with C.

Link to comment
Share on other sites

hehe, yes i will be given pre-written c++ to turn into an extension this way. My level of skill with C and C++ is entry-level at best.

But yes, since php extensions should be written in C i fully agree with you. :)

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.