Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Написание внешних Си функций под Win / 6 сообщений из 6, страница 1 из 1
01.02.2008, 11:22
    #35102995
brbrbr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Написание внешних Си функций под Win
Доброго времени суток.

Есть необходимость переписать ряд функций с pgplsql на Си. Но при этом возникает целый ряд проблем. Пользуюсь SPI интерфейсом, пишу по аналогии с примерами из документации:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
#include "postgres.h"
#include "executor/spi.h"
#include "fmgr.h"

#ifdef PG_MODULE_MAGIC
	PG_MODULE_MAGIC;
#endif

extern Datum my_spi_func(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(my_spi_func);

Datum my_spi_func(PG_FUNCTION_ARGS)
{
	SPI_connect();
	SPI_exec("CREATE TABLE test_table (x int4);",  0 );
	SPI_finish();
	PG_RETURN_INT32( 0 );
}

И .def файл:
Код: plaintext
EXPORTS my_spi_func

При компиляции получаю unresolved external error-ы на все три SPI_ функции. Не хватает .lib файлов. Ищу spi.lib - отсутствует. Где-то на форуме читал совет подключать к проекту postgres.lib, но он у меня тоже отсутствует (искал в установленном из бинарников сервере и в исходниках сервера). Стал искать .dll, в которых экспортируются эти функции, нашёл - в postgres.exe.

Тогда делаю следующим образом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
#include <stdio.h>
#include <windows.h>
#include "postgres.h"
#include "fmgr.h"

#ifdef PG_MODULE_MAGIC
	PG_MODULE_MAGIC;
#endif

extern Datum test_proc(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(test_proc);

typedef int (*dtSPI_void)(void);
typedef int (*dtSPI_exec)(char *, int);

Datum test_proc(PG_FUNCTION_ARGS)
{
	HINSTANCE hinstLib;
	dtSPI_void zSPI_connect;
	dtSPI_void zSPI_finish;
	dtSPI_exec zSPI_exec;

	hinstLib = LoadLibrary("c:/program files/postgresql/8.1/bin/postgres.exe");
	zSPI_connect = (dtSPI_void)GetProcAddress(hinstLib, "SPI_connect");
	zSPI_finish = (dtSPI_void)GetProcAddress(hinstLib, "SPI_finish");
	zSPI_exec = (dtSPI_exec)GetProcAddress(hinstLib, "SPI_exec");

	zSPI_connect();
	zSPI_exec("CREATE TABLE test_table (x int4);",  0 );
	zSPI_finish();

	FreeLibrary(hinstLib);
	PG_RETURN_INT32( 0 );
}

Ну и .def файл, соответственно:
Код: plaintext
EXPORTS test_proc

Делаю так - компилируется и корректно работает.

Едем дальше, добавляю в код строчки:
Код: plaintext
1.
2.
int4 numargs;
...
numargs = PG_NARGS();

При вызове функции из postgre вылетает с ошибкой чтения памяти, роняя запустивший её процесс. При этом все PG_RETURN_ функции работают исправно. В postgre функцию запускаю так:
Код: plaintext
1.
2.
3.
4.
CREATE OR REPLACE FUNCTION pg_temp_1.test_proc(int4) RETURNS int4
AS 'c:/myway/mydll.dll', 'test_proc'
LANGUAGE C;

SELECT pg_temp_1.test_proc( 1 );

Ошибка происходит именно при попытке присвоить значение функции PG_NARGS() какой-нить переменной (или запихнуть её значение в строку через sprintf(sqlbuf, "%d", PG_NARGS())). Если просто вызвать её, ошибки не возникает.


Собственно говоря, вопрос: что я делаю не так? И как правильно пользоваться прилагаемыми средствами разработки? Потому что динамически грузить функции из .dll-ки - это через известное место, причём, как показывает практик, тоже не выход, а ни один из примеров (из того же /contrib) не компилируется, ругаясь на unresolved external symbol в большом количестве.


Используемая софтина:
WinXP
PostgreSQL 8.1.4
Visual Studio 6
...
Рейтинг: 0 / 0
01.02.2008, 11:57
    #35103165
brbrbr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Написание внешних Си функций под Win
Забыл написать.

Пробовал подключать к проекту файл libpostgres.a (который имхо и является тем самым postgres.lib, одновременно инклудя spi.h), но в таком случае сначала получал несколько предупреждений линковщика об исключении неиспользуемых функций на стадии оптимизации, а при подключении .dll и вызове функции из postgre опять же ошибку чтения памяти.

В коде это выглядело так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
#include "postgres.h"
#include "executor/spi.h"

#ifdef PG_MODULE_MAGIC
	PG_MODULE_MAGIC;
#endif

extern Datum test_proc(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(test_proc);

Datum test_proc(PG_FUNCTION_ARGS)
{
	SPI_connect();
	SPI_finish();
}

Соответственно, .def файл:
Код: plaintext
EXPORTS test_proc

И libpostgres.a в качестве дополнительной объектной библиотеки в настройках проекта.
...
Рейтинг: 0 / 0
01.02.2008, 14:19
    #35103780
Написание внешних Си функций под Win
Мне кажется, dll под Postgres рекомендуется собирать с помощью MinGW. По крайней мере, ваш первый пример собрался без проблем, и работает нормально. Где-то на форуме было подробное описание, как это делать.
...
Рейтинг: 0 / 0
01.02.2008, 15:35
    #35104197
brbrbr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Написание внешних Си функций под Win
Золотая рыбкаМне кажется, dll под Postgres рекомендуется собирать с помощью MinGW. По крайней мере, ваш первый пример собрался без проблем, и работает нормально. Где-то на форуме было подробное описание, как это делать.
Спасибо за наводку, буду копать в этом направлении.

А какие-нить либы инклудились? И какие дополнительные пути инклуда (из установленного сервера) прописывались в настройках студии?
...
Рейтинг: 0 / 0
01.02.2008, 16:51
    #35104655
Написание внешних Си функций под Win
Вот тут описано, как с MinGW компилить - тынц
Студия там вообще не используется - компилятор gcc.
...
Рейтинг: 0 / 0
05.02.2008, 12:33
    #35110431
brbrbr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Написание внешних Си функций под Win
Спасибо! Помогло!
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Написание внешних Си функций под Win / 6 сообщений из 6, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]