php.de

Zurück   php.de > Webentwicklung > PHP Einsteiger > PHP Tipps 2008

 
 
LinkBack Themen-Optionen Thema bewerten
Alt 08.04.2008, 14:29  
Neuer Benutzer
 
Registriert seit: 08.04.2008
Beiträge: 8
Han Solo befindet sich auf einem aufstrebenden Ast
Standard Erstellung einer Extension mit Einbindung externer DLL

Hallo,

ich bin ganz neu hier und das, weil ich bei einem Problem einfach nicht weiter weiß. Vielleicht kann mir jemand den entscheidenden Tipp geben zur Lösung des Problems.

Lange Rede, kurzer Sinn, es geht um die Erstellung einer PHP Extension die eine andere DLL (keine PHP Bibliothek) einbindet und Funktionen aus dieser verwenden soll.

Das ganze programmiere ich in Visual Studio C++ 2005 (Express Edition).
Eine simple Extension, die anhand von Parametern eine Berechnung macht oder einen Paramter als Text ausgibt, habe ich geschrieben (unter Zuhilfenahme dieses Tutorials) und sie funktioniert auch in meiner PHP Umgebung (Windows Server 2003, IIS, PHP, MySQL).
Gehe ich nun jedoch dazu über, eine externe Bibliothek einzubinden, kompiliere das ganze (ohne Fehler) und lade diese Extension in PHP, so funktionieren weder die vormals lauffähigen Funktionen noch die neuen, die auf die externe DLL zugreifen. Genauer gesagt wird die Extension nicht mal von PHP geladen, denn sie taucht in der php.ini nicht mehr auf.
Die externe DLL ist eine Windows DLL des Little Color Management.
Im Anschluss habe ich mal meinen Code der Extension, woran vielleicht schon erkannt werden kann, was mein Fehler ist.
PHP-Code:
#include "stdafx.h"
#include "LittleCMS.h"

/* declaration of functions to be exported */
ZEND_FUNCTION(DoubleUp);
PHP_FUNCTION(hello_greetme);
PHP_FUNCTION(convert_rgb_to_cmyk);

/* compiled function list so Zend knows what's in this module */
zend_function_entry CustomExtModule_functions[] = {
    
ZEND_FE(DoubleUpNULL)
    
PHP_FE(hello_greetmeNULL)
    
PHP_FE(convert_rgb_to_cmykNULL)
    {
NULLNULLNULL}
};

/* compiled module information */
zend_module_entry CustomExtModule_module_entry = {
    
STANDARD_MODULE_HEADER,
    
"CustomExt Module",
    
CustomExtModule_functions,
    
NULLNULLNULLNULLNULL,
    
NO_VERSION_YETSTANDARD_MODULE_PROPERTIES
};

/* implement standard "stub" routine to introduce ourselves to Zend */
ZEND_GET_MODULE(CustomExtModule)

/* DoubleUp function */
/* This method takes 1 parameter, a long value, returns the value multiplied by 2 */
ZEND_FUNCTION(DoubleUp)
{
    
long paramValue 0;
    if (
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC"l", &paramValue) == FAILURE) {
        
RETURN_STRING("Bad parameters!"true);
    }
    
paramValue *= 2;
    
RETURN_LONG(paramValue);
}

/* hello_greetme function */
/* This method takes 1 parameter, a string value, returns the value combined with a Hello... */
PHP_FUNCTION(hello_greetme)
{
    
char *name;
    
int name_len;

    if (
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC"s", &name, &name_len) == FAILURE) {
        
RETURN_NULL();
    }

    
php_printf("Hello %s "name);

    
RETURN_TRUE;
}

/* Transform an image from RGB->CMYK */
/* This method takes 3 parameters:
    - a string with the rgb profile filename
    - a string with the cmyk profile filename
    - a string with the image file to be transformed */
PHP_FUNCTION(convert_rgb_to_cmyk)
{
    
char *imagefilename;
    
char *rgbprofilename;
    
char *cmykprofilename;
    
    
CLittleCMS cms;
    
cmsHPROFILE profileRgb;
    
cmsHPROFILE profileCMYK;

    if(!
cms.init("LCMS.DLL"))
    {
        
printf("Failed to load the lcms DLL\n");
        
//return(0);
    
}

    if (
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC"s", &imagefilename, &rgbprofilename, &cmykprofilename) == FAILURE)
    {
        
RETURN_STRING("Wrong parameters!"true);
    }

    
// Load ICC profiles
    
profileRgb cms.cmsdOpenProfileFromFile(rgbprofilename"r");
    
profileCMYK cms.cmsdOpenProfileFromFile(cmykprofilename"r");
    
    
php_printf("Opened Profile: %s "cms.cmsdTakeProductName(profileRgb));
    
php_printf("Opened Profile: %s "cms.cmsdTakeProductName(profileCMYK)); 

    
cms.cmsdCloseProfile(profileRgb);
    
cms.cmsdCloseProfile(profileCMYK);
    
    
RETURN_TRUE;

Die Kompilierung des Projektes funktioniert, wie bereits geschrieben, tadellos. Ich habe Zugriff auf die Methoden der lcms DLL.
Wenn diese nun kompilierte Extension jedoch eingebunden werden soll, wird sie das nicht. In der Windows Ereignisanzeige konnte ich keinen Eintrag finden, dass die DLL beim Starten des IIS nicht korrekt geladen werden konnte, daher weiß ich leider auch nicht weiter, wie ich herausfinden kann, woran es liegt.
Die lcms DLL habe ich sowohl im Linker des Projektes mit der zugehörigen .lib angegeben, als auch wie zu sehen, die Header Datei in die Quelltextdatei eingebunden.


Bis denne, Han Solo
Han Solo ist offline  
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 08.04.2008, 17:56  
Erfahrener Benutzer
 
Benutzerbild von David
 
Registriert seit: 05.09.2007
Beiträge: 5.044
David wird schon bald berühmt werden
Standard

Zitat:
Zitat von Han Solo Beitrag anzeigen
Genauer gesagt wird die Extension nicht mal von PHP geladen, denn sie taucht in der php.ini nicht mehr auf.
Damit ist die Ausgabe von phpinfo() gemeint?
Windows muss die "andere" DLL zur Laufzeit finden können. Wo liegen denn die Dateien?
David ist offline  
Alt 09.04.2008, 09:34  
Neuer Benutzer
 
Registriert seit: 08.04.2008
Beiträge: 8
Han Solo befindet sich auf einem aufstrebenden Ast
Standard

Ja genau, es wird nicht mit phpinfo() angezeigt.
Inzwischen jedoch, nachdem ich die andere DLL, also die, die ich in meine Extension einbinde, noch einmal neu kompiliert habe, funktioniert die Extension.
Das ist aber zuviel gesagt, zwar sind die simplen Methoden der Berechnung und Textausgabe funktionsfähig, doch beim ausführen der anderen, neuen Methode, die intern Methoden der eingebundenen DLL aufruft, bekomme ich nun die Fehlermeldung PHP has encountered an Access Violation at 01D041FB.
Die externe DLL liegt im "ext" Verzeichnis von PHP, genau wie eben die Extension, die diese auch nutzt. Der IIS hat Lese- und Schreibrechte, inklusive Ausfürhren, was also auch irgendwie nicht der Grund sein kann.
Zuerst habe ich vermutet, der IIS bzw. PHP kann die DLL nicht includieren, aber scheint ja nicht so zu sein.
Wird die Methode, welche die DLL Methode anspricht, nicht aufgerufen, gibt es keine Zugriffsverletzung.


Bis denne, Han Solo
Han Solo ist offline  
Alt 09.04.2008, 09:56  
Erfahrener Benutzer
 
Benutzerbild von David
 
Registriert seit: 05.09.2007
Beiträge: 5.044
David wird schon bald berühmt werden
Standard

Bau mal in die Funktion einen DebugBreak() ein und lass Dir einen Debug-Build erstellen. Dann kannst Du Dich mit dem Debugger im Visual Studio ein bisschen umsehen. DebugBreak Function (Windows)

In den Compiler-Flags von beiden DLLs solltest Du jeweils eines der folgenden Flags finden: /MD, /MT, /LD (beim Debug-Build hängt da immer noch ein kleines d dran). Welches dieser drei Flags ist bei den Projekten gesetzt?

David ist offline  
Alt 09.04.2008, 10:50  
Neuer Benutzer
 
Registriert seit: 08.04.2008
Beiträge: 8
Han Solo befindet sich auf einem aufstrebenden Ast
Standard

In meiner PHP Extension ist /MTd bei den Compileroptions angegeben.

Es besteht leider das Problem, dass ich auf einem Vista Rechner mit Studio 2005 die Extension erstelle, dort jedoch kein PHP mit IIS installiert habe. Ausgeführt wird das ganze dann auf einem anderen PC, der widerum kein Studio installiert hat.

Was ich auch noch anmerken möchte. Wie mir gerade aufgefallen ist. Der Access Violation Fehler wird auch geworfen wenn ich die Methode aufrufe ohne irgendetwas zu tun. Genauer gesagt, nachdem ich die Anzahl der Parameter der Methode auf 3 erhöht habe.

Mein PHP Extension Code sieht aktuell so aus:
PHP-Code:
#include "stdafx.h"
#include "lcms.h"
#include "icc34.h"

bool file_exists(const char filename)
{
    if (
FILE file fopen(filename"r"))
    {
        
fclose(file);
        return 
true;
    }
    return 
false;
}

/* declaration of functions to be exported */
ZEND_FUNCTION(DoubleUp);
PHP_FUNCTION(hello_greetme);
PHP_FUNCTION(convert_rgb_to_cmyk);

/* compiled function list so Zend knows what's in this module */
zend_function_entry CustomExtModule_functions[] = {
    
ZEND_FE(DoubleUpNULL)
    
PHP_FE(hello_greetmeNULL)
    
PHP_FE(convert_rgb_to_cmykNULL)
    {
NULLNULLNULL}
};

/* compiled module information */
zend_module_entry CustomExtModule_module_entry = {
    
STANDARD_MODULE_HEADER,
    
"CustomExt Module",
    
CustomExtModule_functions,
    
NULLNULLNULLNULLNULL,
    
NO_VERSION_YETSTANDARD_MODULE_PROPERTIES
};

/* implement standard "stub" routine to introduce ourselves to Zend */
ZEND_GET_MODULE(CustomExtModule)

/* DoubleUp function */
/* This method takes 1 parameter, a long value, returns the value multiplied by 2 */
ZEND_FUNCTION(DoubleUp)
{
    
long paramValue 0;
    if (
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC"l", &paramValue) == FAILURE) {
        
RETURN_STRING("Bad parameters!"true);
    }
    
paramValue *= 2;
    
RETURN_LONG(paramValue);
}

/* hello_greetme function */
/* This method takes 1 parameter, a string value, returns the value combined with a Hello... */
PHP_FUNCTION(hello_greetme)
{
    
char *name;
    
int name_len;

    if (
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC"s", &name, &name_len) == FAILURE) {
        
RETURN_NULL();
    }

    
php_printf("Hello %s "name);

    
RETURN_TRUE;
}

/* Transform an image from RGB->CMYK */
/* This method takes 3 parameters:
    - a string with the rgb profile filename
    - a string with the cmyk profile filename
    - a string with the image file to be transformed */
PHP_FUNCTION(convert_rgb_to_cmyk)
{
    
char *imagefilename;
    
char *rgbprofilename;
    
char *cmykprofilename;
    
    
cmsHPROFILE profileRgb;
    
cmsHPROFILE profileCMYK;

    
    if (
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC"sss", &imagefilename, &rgbprofilename, &cmykprofilename) == FAILURE)
    {
        
RETURN_STRING("Wrong parameters!"true);
    }

    
// Load ICC profiles
    //profileRgb = cms.cmsdOpenProfileFromFile(rgbprofilename, "r");
    //profileCMYK = cms.cmsdOpenProfileFromFile(cmykprofilename, "r");
    //profileRgb = cmsOpenProfileFromFile(rgbprofilename, "r");
    //profileCMYK = cmsOpenProfileFromFile(cmykprofilename, "r");
    
    //php_printf("Opened Profile: %s ", cms.cmsdTakeProductName(profileRgb));
    //php_printf("Opened Profile: %s ", cms.cmsdTakeProductName(profileCMYK));
    //php_printf("Opened Profile: %s ", cmsTakeProductName(profileRgb));
    //php_printf("Opened Profile: %s ", cmsTakeProductName(profileCMYK));

    //cms.cmsdCloseProfile(profileRgb);
    //cms.cmsdCloseProfile(profileCMYK);
    //cmsCloseProfile(profileRgb);
    //cmsCloseProfile(profileCMYK);

    
RETURN_TRUE;

Der Aufruf der Methode in PHP sieht wie folgt aus:
PHP-Code:
<?php
$value 
14;
$result DoubleUp($value);
print 
"Calling DoubleUp($value) returned $result";


echo 
"<br />";
$name "Blub";
hello_greetme($name);

// imagefilename, rgbprofilename, cmykprofilename
convert_rgb_to_cmyk("""rgb.icm""cmyk.icc");
?>

Bis denne, Han Solo
Han Solo ist offline  
Alt 09.04.2008, 11:30  
Erfahrener Benutzer
 
Benutzerbild von David
 
Registriert seit: 05.09.2007
Beiträge: 5.044
David wird schon bald berühmt werden
Standard

Zitat:
Zitat von Han Solo Beitrag anzeigen
Es besteht leider das Problem, dass ich auf einem Vista Rechner mit Studio 2005 die Extension erstelle, dort jedoch kein PHP mit IIS installiert habe.
Kannst Du das ändern? Oder auf dem IIS Rechner die Remote Debugger Komponenten installieren (wobei ich nicht weiss, ob die Express Version das mitmacht)?
Die "externe" Bibliothek hast Du nicht selbst übersetzt?
David ist offline  
Alt 09.04.2008, 12:55  
Neuer Benutzer
 
Registriert seit: 08.04.2008
Beiträge: 8
Han Solo befindet sich auf einem aufstrebenden Ast
Standard

Das wird ein Produktivsystem, wo ich nicht allzuviel schrauben will. Bin kein Systemadministrator, muss aber in dem Fall sehr viel von dessen Arbeit übernehmen. Daher sind mir Eingriffe, die ich nicht 100%ig sicher machen kann, und wo ich nicht gewähren kann, dass damit keine Sicherheitslücken entstehen, nicht sehr willkommen.
Das schränkt ungemein ein, ich weiß, doch leider bleibt mir nichts anderes übrig.

Die andere DLL hab ich selber kompiliert. Damit war es mir möglich, sie überhaupt fehlerfrei zu laden und es wurde die Extension von PHP erkannt.
Bei der DLL handelt es sich um das Little Color Management. Als Source nutzte ich diesen, ludt das Visual Studio VC Projekt und kompilierte nur das lcms Projekt. Bekam damit eine lcmsd.lib und eine lcmsd.dll. Alles entsprechend in mein PHP Extension Projekt kopiert, im Linker eingebunden (die .lib), die .h includiert und hab damit Zugriff auf die Methoden der DLL.

Was mir nun jedoch auch auffällt ist, dass auch bei auskommentierten Codezeilen die Extension den Zugriffsfehler erzeugt. Ich habe die auskommentierten Codezeilen zum erzeugen von Variablen eines Typs der lcms DLL jetzt nochmal komplett rausgeworfen und die Methode warf keinen Error beim simplen php_printf() zum Anzeigen des übergebenen Parameters.
Danach erweiterte ich die Methode auf 3 Parameter
PHP-Code:
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC"sss", &imagefilename, &rgbprofilename, &cmykprofilename) == FAILURE
und war auch gewillt, diese auszugeben, bekam dann jedoch sofort wieder eine Access Violation.
Irgendwie will mir das nicht in den Kopf gehen, was das Problem daran ist und warum beim ändern der Parameteranzahl schon einen Zugriffsfehler bekomme. Auch bei den anderen Methoden, die mit einem Parameter funtkionieren, tritt der Zugriffsfehler auf, wenn ich die Parameteranzahl erhöhe und entprechend viele Parameter übergebe. Werden zu wenig Parameter übergeben, gibt PHP die Fehlermeldung
Warning: hello_greetme() expects exactly 2 parameters, 1 given in C:\Inetpub\wwwroot\testext.php on line 9
aus. Bei zuvielen Parametern wie gesagt die Access Violation.

Mache ich einen Fehler bei der Definition der Anzahl der Parameter oder beim instanzieren der Variablen des eingebundenen DLL?


Bis denne, Han Solo
Han Solo ist offline  
Alt 09.04.2008, 13:58  
Erfahrener Benutzer
 
Benutzerbild von David
 
Registriert seit: 05.09.2007
Beiträge: 5.044
David wird schon bald berühmt werden
Standard

Debugger auf dem Produktivsystem geht nicht, ok. Geht IIS auf dem Entwicklungsrechner? Wenn nicht, versuch es doch mal mit einem Apache auf dem Entwicklungsrechner.
David ist offline  
Alt 09.04.2008, 17:29  
Neuer Benutzer
 
Registriert seit: 08.04.2008
Beiträge: 8
Han Solo befindet sich auf einem aufstrebenden Ast
Standard

Ich habe nun auf dem Entwicklungssystem den IIS inklusive PHP eingerichtet und die Extension eingebunden. Es tritt der gleiche Fehler auf.
Sowie ich mehr als einen Parameter an die Funktionen übergebe (die z.B. 2 erwartet) wird die Access Violation geworfen.

Also wäre an dieser Stelle ein Debuggen der PHP Extension sinnvoll? Nur wie mache ich das, wenn die im ./ext Verzeichnis von PHP liegt.

Diese PHP Extension Programmierung ist für mich totales Neuland und deswegen mögen manche Fragen komisch klingen.


Bis denne, Han Solo
Han Solo ist offline  
Alt 09.04.2008, 19:37  
Erfahrener Benutzer
 
Benutzerbild von David
 
Registriert seit: 05.09.2007
Beiträge: 5.044
David wird schon bald berühmt werden
Standard

Zitat:
Zitat von David Beitrag anzeigen
Bau mal in die Funktion einen DebugBreak() ein und lass Dir einen Debug-Build erstellen. Dann kannst Du Dich mit dem Debugger im Visual Studio ein bisschen umsehen. DebugBreak Function (Windows)
Genau das. Wenn Du einen Debug-Build erstellst bekommst Du .pdb Dateien (IIRC) in denen weitere Debug-Informationen für den Debugger stehen. Die kannst Du auch einfach in das ext Verzeichnis kopieren. Wenn nicht, fragt das Visual Studio bei Bedarf nach dem Ort der .pdb Datei (wie gesagt, wenn ich mich richtig erinnere).
Sobald das Programm auf die DebugBreak Anweisung trifft, wird eine Ausnahme erzeugt und Windows fragt nach, ob und womit das Programm debugged werden soll (es sei denn ein entsprechender handler wurde eingebaut)
David ist offline  
 


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Probleme mit mbstring extension unter Debian HStev Server, Hosting und Workstations 3 30.08.2006 20:55
php5 soap extension, soap attachment zcmaster PHP-Fortgeschrittene 0 07.08.2006 16:09
Problem mit der Einbindung einer Extension schiff PHP Tipps 2006 1 14.06.2006 19:59
PHP IMAP Extension PHP Tipps 2007 8 30.12.2005 15:22
PHP extension und PHPAdmin PHP Tipps 2005 7 15.07.2005 14:26
[Erledigt] Bluetooth extension PHP-Fortgeschrittene 2 05.07.2005 21:29
Installieren der Extension php_iconv.dll MerlinderZauberer PHP Tipps 2005 1 16.04.2005 03:13
PHP5 Extension PHP Tipps 2005 1 11.01.2005 09:03
[Erledigt] SOAP/Client.php: PHP Fatal error: Method SOAP_Client::__call PHP-Fortgeschrittene 6 25.11.2004 09:48

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
php dll, php dll erstellen, php dll aufrufen, dll php, php dll laden, dll in php, php und dll, php function extension c, php dll zugriff, dll mit php, dll für php schreiben, php com dll, php windows dll, php externe dll, php extensions selber schreiben, mit php auf dll, dll für php, php dll registrieren, http://www.php.de/php-tipps-2008/838-erstellung-einer-extension-mit-einbindung-externer-dll.html, php5.2 externe extensions

Alle Zeitangaben in WEZ +1. Es ist jetzt 19:42 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum