Mapbasic: передача параметров функции по ссылке

MapInfo, MapBasic
Аватара пользователя
Juls
Интересующийся
Сообщения: 49
Зарегистрирован: 02 авг 2010, 10:30
Репутация: 1

Mapbasic: передача параметров функции по ссылке

Сообщение Juls » 24 июн 2011, 14:19

Здравствуйте, Есть DLL библиотека написанная на C++, и там параметры функции передаются по ссылке. Есть ли возможность подключить ее к mapbasic?

SergS
Активный участник
Сообщения: 119
Зарегистрирован: 14 апр 2011, 13:24
Репутация: 5
Откуда: Екатеринбург

Re: Mapbasic: передача параметров функции по ссылке

Сообщение SergS » 27 июн 2011, 05:32

а есть вообще только 2 способа передачи параметров в функцию - по значению и по ссылке. синтаксически в С++ различают по ссылке и указатели, но эти языковые нюансы сути не меняют: по ссылке - это значит - передается значение указателя.
для MB это означает, что параметры простых (т.е. не Type, не массивы, и не string) типов объявляются НЕ используя модификатор Byval.
относительно string - можно уточнить, м.б. что и изменилось, но даже изменяемую в DLL строку передаем как Byval (все равно сложные типы в MB передаются по ссылке, но адрес начала строки в сишном стиле формируется при использовании Byval), если нет, то стандартные системные Dll-ки (при их использовании) частенько рубят Mapinfo.

Аватара пользователя
Juls
Интересующийся
Сообщения: 49
Зарегистрирован: 02 авг 2010, 10:30
Репутация: 1

Re: Mapbasic: передача параметров функции по ссылке

Сообщение Juls » 27 июн 2011, 15:51

допустим в dll описана функция int MyFunction(char * sbuff, int *ival, char * s)

вызываю из мапбейсика след образом:

declare function MyFunction "Mydll.dll" (sbuff as string, ival as integer, comment as string) as integer
declare sub main

sub main
dim sbuff, comment as string,
ival, i_return as integer
sbuff="this is test"
i_return = MyFunction(sbuff,ival,comment)
end sub


возникает ошибка "внешняя библиотека не содержит функцию MyFunction" ? в чем проблема?

SergS
Активный участник
Сообщения: 119
Зарегистрирован: 14 апр 2011, 13:24
Репутация: 5
Откуда: Екатеринбург

Re: Mapbasic: передача параметров функции по ссылке

Сообщение SergS » 28 июн 2011, 04:53

а две причины для такой ошибки:
1) ваша функция, которая MyFunction, является не экспортируемой;
2) ваша функция, которая MyFunction, называется совсем не MyFunction.
в первом случае, что называется - ССЗБ :)
во втором, чтоб не рыться в настройках компилятора и линковщика используйте такую замечательную штуку, как tdump.exe - посмотрите, что на самом деле записано в секции exports. И будте готовы, что компилятор напихал в имя функции кучу всякой фигни (в лучшем случае это будет знак подчеркивания в начале имени)

ну еще, вроде в строке

Код: Выделить всё

declare function MyFunction "Mydll.dll" (sbuff as string, ival as integer, comment as string) as integer
пропущено слово "Lib" перед именем файла dll

Аватара пользователя
asgs
Участник
Сообщения: 89
Зарегистрирован: 04 авг 2010, 06:35
Репутация: 0
Контактная информация:

Re: Mapbasic: передача параметров функции по ссылке

Сообщение asgs » 28 июн 2011, 06:06

Обратите еще внимание, если dll-ку лепите в С++, используйте в описании функций способ вызова stdcall (влияет на порядок передачи параметров и очистку стека вызовов). По умолчанию с С++ используется fastcall, так что можно налететь на неприятные грабли.
Удачи.
Злобный йожег

Аватара пользователя
Juls
Интересующийся
Сообщения: 49
Зарегистрирован: 02 авг 2010, 10:30
Репутация: 1

Re: Mapbasic: передача параметров функции по ссылке

Сообщение Juls » 28 июн 2011, 11:12

спасибо, за советы. способ вызова стоит stdcall. tdump показывает следующее:
Exports from MType.dll
1 exported name(s), 1 export addresse(s). Ordinal base is 1.
Sorted by Name:
RVA Ord. Hint Name
-------- ---- ---- ----
00001010 1 0000 ?Char2Int@@YGHPADPAH0@Z
что означают символы после имени функции Char2Int? и как отключить декорирование функций в VSc++2008?

Аватара пользователя
asgs
Участник
Сообщения: 89
Зарегистрирован: 04 авг 2010, 06:35
Репутация: 0
Контактная информация:

Re: Mapbasic: передача параметров функции по ссылке

Сообщение asgs » 28 июн 2011, 12:00

Для VC++ 2008 можно посмотреть как пример вот это: http://asgs.narod.ru/downloads/gpl/TiffMosaicSrc.rar
Там как раз библиотека под MapBasic.
Про декорацию имен функций - если мне не сильно изменяет склероз, нужно в файле *.def в секции EXPORTS создать список имен экспортируемых функций. В примере это должно быть.
Злобный йожег

SergS
Активный участник
Сообщения: 119
Зарегистрирован: 14 апр 2011, 13:24
Репутация: 5
Откуда: Екатеринбург

Re: Mapbasic: передача параметров функции по ссылке

Сообщение SergS » 28 июн 2011, 12:13

декорирование имен функций - это фишка C++, связанная с возможностью перегрузки функций.
в VS не знаю (как то не сложились отношения с компиляторами от MS), а в Борланд это решалось при объявлении функции примерно вот так:
extern "C" int Char2Int(...)
ну и stdcall cоответственно тоже надо...

все это прямые директивы компилятору, соответственно лазить во всякие доп. фалы не приходилось.

Аватара пользователя
Juls
Интересующийся
Сообщения: 49
Зарегистрирован: 02 авг 2010, 10:30
Репутация: 1

Re: Mapbasic: передача параметров функции по ссылке

Сообщение Juls » 28 июн 2011, 15:11

Спасибо Все получилось. с использованием def файла.

Подскажите еще можно ли както экспортировать в мапбейсик из dll константы определенные директивой #define?

SergS
Активный участник
Сообщения: 119
Зарегистрирован: 14 апр 2011, 13:24
Репутация: 5
Откуда: Екатеринбург

Re: Mapbasic: передача параметров функции по ссылке

Сообщение SergS » 28 июн 2011, 15:45

Будете смеятся, но у вас в dll нет констант, определенных "директивой #define" они существуют только в исходном коде, после компиляции - увы, нету их. Это чисто подстановочные значения, компилятор еще до собственно компиляции как только встретит значение из #define, сразу заменяет его выражением (именно текстом, даже не вычисляя выражения) из того же #define.
если хотите в программе на MB использовать такие же именованные константы, скопируйте их определения из с-шного кода в отдельный файл с раширением def (принято в MB), удалите символы # и ; - получите вполне такой заголовочный файл для MB. Подключать оператором Include. (аналогично mapbasic.def)

Аватара пользователя
Juls
Интересующийся
Сообщения: 49
Зарегистрирован: 02 авг 2010, 10:30
Репутация: 1

Re: Mapbasic: передача параметров функции по ссылке

Сообщение Juls » 28 июн 2011, 16:50

Понятно, спасибо

вопрос еще такой, насколько я поняла декорирование функций необходимо для возможности перегрузки функций? т.е. в dll под mapbasic перегрузка функций не может быть использована?

Аватара пользователя
asgs
Участник
Сообщения: 89
Зарегистрирован: 04 авг 2010, 06:35
Репутация: 0
Контактная информация:

Re: Mapbasic: передача параметров функции по ссылке

Сообщение asgs » 29 июн 2011, 04:14

Насколько я помню, MapBasic не поддерживает перегрузку функций, по крайней мере пользовательских. Хотя встроенные функции, судя по всему, вполне себе перегруженные.
ЗЫ Блин, не совсем понял вопрос. Видимо, перегрузку функций из dll использовать будет затруднительно, поскольку в MapBasic-е они также рассматриваются как пользовательские.
Злобный йожег

SergS
Активный участник
Сообщения: 119
Зарегистрирован: 14 апр 2011, 13:24
Репутация: 5
Откуда: Екатеринбург

Re: Mapbasic: передача параметров функции по ссылке

Сообщение SergS » 29 июн 2011, 05:11

Внутри dll пожалуйста, можно использовать все возможности языка. А экспортировать перегруженные функции бесполезно - компилятор не даст экспортировать различные (а перегруженные функции все равно ведь различные, хотя и кажется, что одинаково называются) функции под одним именем.

Vladislav
Новоприбывший
Сообщения: 6
Зарегистрирован: 04 окт 2011, 12:11
Репутация: 0
Откуда: Томск

Re: Mapbasic: передача параметров функции по ссылке

Сообщение Vladislav » 04 окт 2011, 12:56

Добрый день.
Еще один вопрос в ту же тему.
Исходные данные: использую MapBasic 9.5 + Visual Studio 2010 (C#)
На C# сделана dll:

Код: Выделить всё

namespace MIL 
{ public class MIC  
  { public static unsafe void GetMapIdFromDB(int Идентификатор_карты) // можно и без unsafe
    { MessageBox.Show(Convert.ToString(Идентификатор_карты)); } 
  }
}
В MapBasic описываю эту внешнюю функцию (лежащую в dll):

Код: Выделить всё

Declare method GetMapIdFromDB Class "MIL.MIC" Lib "ClassLibrary1.dll" (ByVal maps_id as integer)
В теле Sub Main программы на MapBasic вызываю эту функцию:

Код: Выделить всё

call GetMapIdFromDB(map_id)
(map_id предварительно описана как int и проинициализирована нулём)
При запуске MapInfo весело отображает окошко с нулём (т.е. ВСЁ РАБОТАЕТ)

Далее в программе на MapBasic в декларативной секции метода убираем слово ByVal .
Получаем:

Код: Выделить всё

Declare method GetMapIdFromDB Class "MIL.MIC" Lib "ClassLibrary1.dll" (maps_id as integer)
Цель: передавать в DLL не само значение переменной, а только ссылку на него. В перспективе DLL подправит значение переменной и MapInfo будет далее работать со значением обновленным в dll .
Проблема: после удаления ключевого слова ByVal при запуске программы на MapBasic появилась ошибка:

Код: Выделить всё

"Не найден метод public, static 'GetMapIdFromDB'. Проверьте имя метода и сигнатуру."
Вопрос: как в Visual Studio 2010 на C# сделать так, чтоб написанная dll все таки могла принимать переменные из MapBasic "по ссылке", а не "по значению" ?

Заранее благодарен за аргументированный ответ.

SergS
Активный участник
Сообщения: 119
Зарегистрирован: 14 апр 2011, 13:24
Репутация: 5
Откуда: Екатеринбург

Re: Mapbasic: передача параметров функции по ссылке

Сообщение SergS » 04 окт 2011, 14:10

а вместо
void GetMapIdFromDB(int Идентификатор_карты)
в объявлении функции написать
void GetMapIdFromDB(int *идентификатор_карты) - т.е функция получит указатель
или так
void GetMapIdFromDB(int& идентификатор_карты) - т.е функция опять таки получит указатель, но обращаться с ним будет как с обычной переменной, т.е разименовывать не потребуется и код править тоже.

Ответить

Вернуться в «MapInfo»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 4 гостя