FreeBasic
Главная
Вход
Регистрация
Вторник, 20.02.2018, 08:21Приветствую Вас Гость | RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
Страница 1 из 11
Форум » Freebasic » Вопросы по языку FreeBasic » Как передать в ф-цию параметр неопределенного типа?
Как передать в ф-цию параметр неопределенного типа?
vic7tarДата: Четверг, 21.12.2017, 04:32 | Сообщение # 1
Рядовой
Группа: Пользователи
Сообщений: 10
Репутация: 0
Статус: Offline
Всем привет.

Код
Declare Sub my_sub (ByRef a ??? )

Dim a As Long = 12567
Dim b As String = "abc"
Dim c As Single = -1.25

my_sub(a)
my_sub(b)
my_sub(c)

Sub my_sub (ByRef param ???)
???
Print param
End Sub
Вопрос такой - возможно реализовать такую функцию (my_sub)?
 
haavДата: Четверг, 21.12.2017, 16:43 | Сообщение # 2
Генерал-полковник
Группа: Администраторы
Сообщений: 827
Репутация: 34
Статус: Offline
Цитата vic7tar ()
Вопрос такой - возможно реализовать такую функцию (my_sub)?


1) C помощью перегрузки функций , см. пример оператора Overload
2) С помощью OOP , см. пример оператора IS
3) C помощью указателей, но в функции должен быть параметр , для того чтобы отличать типы. Что-то типа:

Код
Enum ePARAM
   
   eByte
   
   eInteger
   
   eZstring
   
End Enum

Dim as Byte bData = 50

Dim As Integer IData = 50000

Dim As ZString*20 sData = "bla bla bla..."

Sub PrintData(pObj As Any Ptr, Param As ePARAM)
   
   Select Case Param
      
      Case eByte
         
         ? "Byte Value= " ; *Cast(Byte Ptr , pObj)
         
      Case eInteger
         
         ? "Integer Value= " ; *Cast(Integer Ptr , pObj)
         
      Case eZstring
         
         ? "zString Value= " ; *Cast(ZString Ptr , pObj)
            
   End Select
   
End Sub

PrintData(@bData , eByte)

PrintData(@iData , eInteger)

PrintData(@sData , eZstring)

Sleep


4) C помощью указателей , без второго параметра в функции, но придется подсовывать в функцию указатель на структуру, где в одном из полей для отличия указывается неявно тип:

Код
Enum ePARAM
   
   eByte
   
   eInteger
   
   eZstring
   
End Enum

Type T
   
   pObj As Any Ptr
   
   Param As ePARAM
   
End Type

Dim as Byte bData = 50

Dim As Integer IData = 50000

Dim As ZString*20 sData = "bla bla bla..."

Sub PrintData(pObj As Any Ptr)
   
   Dim p As T Ptr = Cast(T Ptr , pObj)
   
   Select Case p->Param
      
      Case eByte
         
         ? "Byte Value= " ; *Cast(Byte Ptr , p->pObj)
         
      Case eInteger
         
         ? "Integer Value= " ; *Cast(Integer Ptr , p->pObj)
         
      Case eZstring
         
         ? "zString Value= " ; *Cast(ZString Ptr , p->pObj)
            
   End Select
   
End Sub

Dim bT As T = Type (@bData , eByte)

Dim iT As T = Type (@iData , eInteger)

Dim sT As T = Type (@sData , eZstring)

PrintData(@bT)

PrintData(@iT)

PrintData(@sT)

Sleep


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
vic7tarДата: Четверг, 21.12.2017, 17:52 | Сообщение # 3
Рядовой
Группа: Пользователи
Сообщений: 10
Репутация: 0
Статус: Offline
haav, спасибо за уделенное время и код.
Привожу пример из Help-а:
Код
'Пример ANY отключающий проверку типа переменной
Declare Sub echo (ByRef a As Any) '' ANY отключает проверку для типа данных, передаваемого в функцию

Dim x As Single
x = -15
echo x                  '' Передаем single в функцию, которая ожидает integer. компилятор не жалуется :)             
Sleep

Sub echo (ByRef a As Integer)
  Print Hex(a)         
End Sub
Он корректен?
В Clarion есть встроенная функция ADDRESS(variable), возвращающая адрес variable, где variable - метка переменной любого типа, структуры, процедуры.
Возможна ли реализация такой функции в FB, в которую параметр передается именно по ByRef?
Чтобы затем оформить ее в dll и использовать в другом языке, где указателей просто нет (имею ввиду Visual FoxPro).


Сообщение отредактировал vic7tar - Четверг, 21.12.2017, 18:23
 
haavДата: Четверг, 21.12.2017, 19:00 | Сообщение # 4
Генерал-полковник
Группа: Администраторы
Сообщений: 827
Репутация: 34
Статус: Offline
Цитата vic7tar ()
Он корректен?


Нет. Сам посмотри на результат вывода. Чтобы лучше было видно, вместо -15 подставь любое положительное число. Возможно в прошлых версиях компилятора такой пример мог нормально работать...

Цитата vic7tar ()
В Clarion есть встроенная функция ADDRESS(variable), возвращающая адрес variable, где variable - метка переменной любого типа, структуры, процедуры.
Возможна ли реализация такой функции в FB, в которую параметр передается именно по ByRef?
Чтобы затем оформить ее в dll и использовать в другом языке, где указателей просто нет (имею ввиду Visual FoxPro).


Не могу сказать, никогда не использовал Visual FoxPro. В FB ключевое слово BYREF это по сути передача адреса. То есть два примера работают одинаково:

Код
Sub proc(ByRef i As integer)
   
   i+=5 ' меняем значение iVar
   
End Sub

Dim As Integer iVar = 15

? iVar ' выводим значение в консоль перед вызовом процедуры

proc(iVar)

? iVar ' выводим значение в консоль после вызова процедуры

sleep


Код
Sub proc( i As Integer Ptr)
   
   *i+=5 ' меняем значение iVar
   
End Sub

Dim As Integer iVar = 15

? iVar ' выводим значение в консоль перед вызовом процедуры

proc(@iVar)

? iVar ' выводим значение в консоль после вызова процедуры

Sleep


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
vic7tarДата: Четверг, 21.12.2017, 19:55 | Сообщение # 5
Рядовой
Группа: Пользователи
Сообщений: 10
Репутация: 0
Статус: Offline
Спасибо за наводку на Overload, получилось вот такое (вроде работает):
Код
Public Function address Pascal Overload  Alias "address" ( ByRef any_input As long) As Long Export
    Return @any_input
End Function

Public Function address Pascal Overload  Alias "address" ( ByRef any_input As String) As Long Export
  Return CLng(StrPtr(any_input))
End Function

Public Function address Pascal Overload  Alias "address" ( ByRef any_input As Single) As Long Export
    Return @any_input
End Function


Сообщение отредактировал vic7tar - Четверг, 21.12.2017, 19:57
 
haavДата: Четверг, 21.12.2017, 20:06 | Сообщение # 6
Генерал-полковник
Группа: Администраторы
Сообщений: 827
Репутация: 34
Статус: Offline
Цитата
Возможна ли реализация такой функции в FB, в которую параметр передается именно по ByVal?


В самом freebasic можно передавать числовые переменные , не соотвествующие типу. Так например данный код будет работать в FB, однако дробные числа будут округляться:

Код
Sub proc(Byval i As integer)
   
   ? i
   
End Sub

Dim As Single singleVar = 15.57

Dim As Byte byteVar =  44

Dim As Double doubleVar = 33.736363

proc(singleVar)

proc(byteVar)

proc(doubleVar)

sleep


Цитата
Чтобы затем оформить ее в dll и использовать в другом языке, где указателей просто нет (имею ввиду Visual FoxPro).


Чтобы что-то утверждать, нужно хорошо знать и freebasic и Visual FoxPro. Даже если напишешь dll на freebasic , нет абсолютно никакой гарантии , что dll-ка будет корректно работать с Visual FoxPro.


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
vic7tarДата: Воскресенье, 24.12.2017, 03:06 | Сообщение # 7
Рядовой
Группа: Пользователи
Сообщений: 10
Репутация: 0
Статус: Offline
DLL, собранные в FB, без проблем  стыкуются в VFP.
haav, помоги, пожалуйста, разобрать дальше.

Собрал библиотеку:
address.dll
Symbol                      Ordinal
_Z7addressR8FBSTRING            1
_Z7addressRf                          2
_Z7addressRl                          3


А как теперь использовать перезагрузку функций в вызывающей процедуре?
Код
Dim As Any Ptr library = DyLibLoad( "address.dll" )
Dim address As Function( ??? ) As Long
address = DyLibSymbol( library, ??? )
Например, если указываю напрямую,
Код
Dim address As Function( ByRef any_input As long ) As Long
address = DyLibSymbol( library, 3 )
то все нормально.
Если так,
Код
address = DyLibSymbol( library, "address" )
то выдает ошибку 7 (нулевой указатель).


Сообщение отредактировал vic7tar - Воскресенье, 24.12.2017, 03:36
 
haavДата: Воскресенье, 24.12.2017, 08:55 | Сообщение # 8
Генерал-полковник
Группа: Администраторы
Сообщений: 827
Репутация: 34
Статус: Offline
перегрузку функций в FB из библиотеки, написанной на FB можно использовать при статическом связывании:

код DLL (1.dll):

Код
Public Function address Pascal Overload  Alias "address" ( ByRef any_input As long) As Long Ptr Export
    Return @any_input
End Function

Public Function address Pascal Overload  Alias "address" ( ByRef any_input As ZString) As zString Ptr Export
  Return StrPtr(any_input)
End Function

Public Function address Pascal Overload  Alias "address" ( ByRef any_input As Single) As Single Ptr Export
    Return @any_input   
End Function


код программы, вызывающей DLL:

Код
#Inclib "1"

Public Function address Pascal Overload  Alias "address" ( ByRef any_input As long) As Long Ptr Export
    Return @any_input
End Function

Public Function address Pascal Overload  Alias "address" ( ByRef any_input As ZString) As zString Ptr Export
  Return StrPtr(any_input)
End Function

Public Function address Pascal Overload  Alias "address" ( ByRef any_input As Single) As Single Ptr Export
    Return @any_input   
End Function

? *address(55.67)
? *address(55)

sleep


При динамическом связывании, я понятия не имею возможно ли использовать перегрузку функций (мне кажется невозможно). Получится только такое:

Код
Dim As Any Ptr library = DyLibLoad( "1.dll" )
Dim addressF As Function(ByRef  As Single ) As single Ptr
Dim addressL As Function(ByRef  As Long ) As Long Ptr
Dim addressS As Function(ByRef  As ZString ) As ZString Ptr
addressF = DyLibSymbol( library, "_Z7addressRf" )
addressS = DyLibSymbol( library, "_Z7addressRc" )

Dim As Single sV = 55.78
Dim As ZString*20 sS = "bla bla bla..."

? *(addressF(sV))
? *(addressS(sS))

sleep

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


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
Форум » Freebasic » Вопросы по языку FreeBasic » Как передать в ф-цию параметр неопределенного типа?
Страница 1 из 11
Поиск: