Forum Webscript.Ru
		Программирование => PHP => Тема начата: Nat от 13 Августа 2002, 18:10:26
		
			
			- 
				Такая проблема :( 
 Есть библиотека (написана в Delphi), которая экспортирует процедуры. В качестве параметров передаются строки PChar.
 Как вызвать эти процедуры в PHP?
 Знаю, что есть такие понятия как extension и функция dl(), но не более. Буду благодарна за помощь.
- 
				Почитай:
 http://www.php.net/manual/en/zend.structure.php#zend.structure.module
 Тут описано как строить модули расширения
- 
				Nat 
 Там не dl() а get_module()
 Советую взять исходники для винды и изучить их
- 
				Спасибо за ответ :-)
 исходники для винды  - какие исходники, не совсем поняла;
 По-поводу статьи по ссылке, я действительно тону... Мне бы что-нибудь более целое в качестве примера. Там вероятно много хорошего написано по англицки, но... как-то картина не вырисовывается. Сложно, или мой англ совсем плох.
- 
				Nat 
 исходники 
 Исходные коды.
 более целое  
 Кусок кода модуля ftp:
 
 #include "php.h"
 
 #if HAVE_FTP
 
 #include
 #include
 #include
 #ifdef HAVE_UNISTD_H
 #include
 #endif
 #include
 #include
 #include
 #ifdef PHP_WIN32
 #include
 #else
 #ifdef HAVE_SYS_TYPES_H
 #include
 #endif
 ...
 /*
 реализация функции ftp_open
 */
 ftp_open(const char *host, short port, long timeout_sec)
 {
 ftpbuf_t		*ftp;
 int			size;
 struct timeval tv;
 
 
 /* alloc the ftp structure */
 ftp = calloc(1, sizeof(*ftp));
 if (ftp == NULL) {
 perror("calloc");
 return NULL;
 }
 
 tv.tv_sec = timeout_sec;
 tv.tv_usec = 0;
 
 ftp->fd = php_hostconnect(host, (unsigned short) (port ? port : 21), SOCK_STREAM, &tv);
 if (ftp->fd == -1) {
 goto bail;
 }
 
 /* Default Settings */
 ftp->timeout_sec = timeout_sec;
 ftp->async = 0;
 
 size = sizeof(ftp->localaddr);
 memset(&ftp->localaddr, 0, size);
 if (getsockname(ftp->fd, (struct sockaddr*) &ftp->localaddr, &size) == -1) {
 perror("getsockname");
 goto bail;
 }
 
 if (!ftp_getresp(ftp) || ftp->resp != 220) {
 goto bail;
 }
 
 return ftp;
 
 bail:
 if (ftp->fd != -1)
 closesocket(ftp->fd);
 free(ftp);
 return NULL;
 }
 /* }}} */
 ...
 
 Заголовочный файл (ftp.h):
 
 #ifndef	FTP_H
 #define	FTP_H
 
 #include "php_network.h"
 
 #include
 #ifdef HAVE_NETINET_IN_H
 #include
 #endif
 
 #define	FTP_DEFAULT_TIMEOUT	90
 #define FTP_DEFAULT_AUTOSEEK 1
 #define PHP_FTP_FAILED			0
 #define PHP_FTP_FINISHED		1
 #define PHP_FTP_MOREDATA		2
 
 /* XXX this should be configurable at runtime XXX */
 #define	FTP_BUFSIZE	4096
 
 typedef enum ftptype {
 FTPTYPE_ASCII,
 FTPTYPE_IMAGE
 } ftptype_t;
 
 typedef struct databuf
 {
 int		listener;		/* listener socket */
 int		fd;			/* data connection */
 ftptype_t	type;			/* transfer type */
 char		buf[FTP_BUFSIZE];	/* data buffer */
 } databuf_t;
 
 typedef struct ftpbuf
 {
 int		fd;			/* control connection */
 php_sockaddr_storage	localaddr;	/* local address */
 int		resp;			/* last response code */
 char		inbuf[FTP_BUFSIZE];	/* last response text */
 char		*extra;			/* extra characters */
 int		extralen;		/* number of extra chars */
 char		outbuf[FTP_BUFSIZE];	/* command output buffer */
 char		*pwd;			/* cached pwd */
 char		*syst;			/* cached system type */
 ftptype_t	type;			/* current transfer type */
 int		pasv;			/* 0=off; 1=pasv; 2=ready */
 php_sockaddr_storage	pasvaddr;	/* passive mode address */
 long	timeout_sec;	/* User configureable timeout (seconds) */
 int			autoseek;	/* User configureable autoseek flag */
 
 int				async;	/* asyncronous transfer in progress */
 databuf_t		*data;	/* Data connection for asyncrounous transfers */
 php_stream		*stream; /* output stream for asyncrounous transfers */
 int				lastch;		/* last char of previous call */
 int				direction;	/* recv = 0 / send = 1 */
 int				closestream;/* close or not close stream */
 } ftpbuf_t;
 
 
 
 /* open a FTP connection, returns ftpbuf (NULL on error)
 * port is the ftp port in network byte order, or 0 for the default
 */
 ftpbuf_t*	ftp_open(const char *host, short port, long timeout_sec);
 
 /* quits from the ftp session (it still needs to be closed)
 * return true on success, false on error
 */
 int		ftp_quit(ftpbuf_t *ftp);
 
 /* frees up any cached data held in the ftp buffer */
 void		ftp_gc(ftpbuf_t *ftp);
 
 /* close the FTP connection and return NULL */
 ftpbuf_t*	ftp_close(ftpbuf_t *ftp);
 
 /* logs into the FTP server, returns true on success, false on error */
 int		ftp_login(ftpbuf_t *ftp, const char *user, const char *pass);
 
 /* reinitializes the connection, returns true on success, false on error */
 int		ftp_reinit(ftpbuf_t *ftp);
 
 /* returns the remote system type (NULL on error) */
 const char*	ftp_syst(ftpbuf_t *ftp);
 
 /* returns the present working directory (NULL on error) */
 const char*	ftp_pwd(ftpbuf_t *ftp);
 
 /* exec a command [special features], return true on success, false on error */
 int 	ftp_exec(ftpbuf_t *ftp, const char *cmd);
 
 /* changes directories, return true on success, false on error */
 int		ftp_chdir(ftpbuf_t *ftp, const char *dir);
 
 /* changes to parent directory, return true on success, false on error */
 int		ftp_cdup(ftpbuf_t *ftp);
 
 /* creates a directory, return the directory name on success, NULL on error.
 * the return value must be freed
 */
 char*		ftp_mkdir(ftpbuf_t *ftp, const char *dir);
 
 /* removes a directory, return true on success, false on error */
 int		ftp_rmdir(ftpbuf_t *ftp, const char *dir);
 
 /* returns a NULL-terminated array of filenames in the given path
 * or NULL on error.  the return array must be freed (but don\'t
 * free the array elements)
 */
 char**		ftp_nlist(ftpbuf_t *ftp, const char *path);
 
 /* returns a NULL-terminated array of lines returned by the ftp
 * LIST command for the given path or NULL on error.  the return
 * array must be freed (but don\'t
 * free the array elements)
 */
 char**		ftp_list(ftpbuf_t *ftp, const char *path, int recursive);
 
 /* switches passive mode on or off
 * returns true on success, false on error
 */
 int		ftp_pasv(ftpbuf_t *ftp, int pasv);
 
 /* retrieves a file and saves its contents to outfp
 * returns true on success, false on error
 */
 int		ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path,
 ftptype_t type, int resumepos);
 
 /* stores the data from a file, socket, or process as a file on the remote server
 * returns true on success, false on error
 */
 int		ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos);
 
 /* returns the size of the given file, or -1 on error */
 int		ftp_size(ftpbuf_t *ftp, const char *path);
 
 /* returns the last modified time of the given file, or -1 on error */
 time_t		ftp_mdtm(ftpbuf_t *ftp, const char *path);
 
 /* renames a file on the server */
 int		ftp_rename(ftpbuf_t *ftp, const char *src, const char *dest);
 
 /* deletes the file from the server */
 int		ftp_delete(ftpbuf_t *ftp, const char *path);
 
 /* sends a SITE command to the server */
 int		ftp_site(ftpbuf_t *ftp, const char *cmd);
 
 /* retrieves part of a file and saves its contents to outfp
 * returns true on success, false on error
 */
 int		ftp_async_get(ftpbuf_t *ftp, php_stream *outstream, const char *path,
 ftptype_t type, int resumepos);
 
 /* stores the data from a file, socket, or process as a file on the remote server
 * returns true on success, false on error
 */
 int		ftp_async_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos);
 
 /* continues a previous async_(f)get command
 */
 int		ftp_async_continue_read(ftpbuf_t *ftp);
 
 /* continues a previous async_(f)put command
 */
 int		ftp_async_continue_write(ftpbuf_t *ftp);
 
 
 #endif
 
 сам модуль находится в  файлах hp_ftp.c php_ftp.h
 Вот как обявляются функции:
 
 * {{{ proto resource ftp_connect(string host [, int port [, int timeout)]])
 Opens a FTP stream */
 PHP_FUNCTION(ftp_connect)
 {
 ftpbuf_t	*ftp;
 char		*host;
 int			host_len, port = 0;
 long		timeout_sec = FTP_DEFAULT_TIMEOUT;
 
 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &host, &host_len, &port, &timeout_sec) == FAILURE) {
 return;
 }
 
 if (timeout_sec <= 0) {
 php_error(E_WARNING, "%s(): Timeout has to be greater than 0",
 get_active_function_name(TSRMLS_C));
 RETURN_FALSE;
 }
 
 /* connect */
 ftp = ftp_open(host, (short)port, timeout_sec);
 if (ftp == NULL) {
 RETURN_FALSE;
 }
 
 /* autoseek for resuming */
 ftp->autoseek = FTP_DEFAULT_AUTOSEEK;
 
 ZEND_REGISTER_RESOURCE(return_value, ftp, le_ftpbuf);
 }
 /* }}} */
 
 /* {{{ proto bool ftp_login(resource stream, string username, string password)
 Logs into the FTP server */
 PHP_FUNCTION(ftp_login)
 {
 zval 		*z_ftp;
 ftpbuf_t	*ftp;
 char *user, *pass;
 int user_len, pass_len;
 
 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &z_ftp, &user, &user_len, &pass, &pass_len) == FAILURE) {
 return;
 }
 
 ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
 
 /* log in */
 if (!ftp_login(ftp, user, pass)) {
 php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
 RETURN_FALSE;
 }
 
 RETURN_TRUE;
 }
 /* }}} */
 
 Если вкратце - в одном файле находятся функции, реализующие более или менее универсальную функциональность, а в другом (php_ftp.c) непосредственно експортируемые функции.
 В лучшем случае тебе придется сделать еще одну библиотеку, которая будет надстройкой над уже существующей
 
 Поясняю:
- 
				Имеется библиотека, написанная на Delphi (далее идет псевдокод библиотеки):
 
 ...
 { Абсолютно бессмысленная функция }
 function LibraryFunction(inputValue : integer) : PChar;
 var
 resultat : string;
 begin
 resultat := IntToStr(inputValue);
 LibraryFunction := str2pchar(resrultat);
 end;
 ...
 
 Интерфейсная библиотека будет выглядеть примерно так (опять же сильно упрощенный псевдокод):
 
 ...
 PHP_FUNCTION(lib_func)
 {
 char * tmp;
 int integer = 0;
 
 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &integer) == FAILURE) {
 return;
 }
 tmp = LibraryFunction(integer);
 RETURN_STRING(tmp, 1);
 
 }
 ...
 
 
 Примерно так...
- 
				Не сочтите за наглость и назойливость,
 но допустим написала интерфейсную библиотеку php_lib.c (там просто прототипы ф-ций PHP_FUNCTION..., как я поняла).
 Куда должны быть помещены файл с самой библиотекой Delphi.dll и php_lib.c ? Или php_lib.c надо скопилировать, а только потом куда-то положить? (просто в С++ окромя значка == ничего не знаю, а значит шансы спасения утопающего близки к 0)
 
 И после всего этого теоретически я могу просто обратиться из кода PHP к любой ф-ции, обявленной в прототипах, по ее имени без указания ее источника (имени библ-ки)?
- 
				Nat 
 Ты должна откомпилить php_lib.c - положить ее в папку extensions и проиписать ее в разделе extensions файла php.ini
 Соответственно, если используется внешняя библиотека (Delphi.dll)- то ее надо положить либо в туже папку, что и php_lib.dll или в системную папку (проще в туже папку)
 
 И после всего этого теоретически  
 Да сможешь. Учитывая, то, что я написал...
- 
				Однозначно ХОРОШИЙ человек без всяких или :-)
 Спасибо!
- 
				Пожалста.
 :)