Как передать в ф-цию параметр неопределенного типа?
|
|
vic7tar | Дата: Четверг, 21.12.2017, 04:32 | Сообщение # 1 |
Рядовой
Группа: Пользователи
Сообщений: 12
Статус: 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 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: 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 |
Рядовой
Группа: Пользователи
Сообщений: 12
Статус: 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 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: 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 |
Рядовой
Группа: Пользователи
Сообщений: 12
Статус: 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 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: 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 |
Рядовой
Группа: Пользователи
Сообщений: 12
Статус: 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 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: 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 На разных языках и диалектах внутренние реализации каких либо техник и методов ( например: наследование ,полиморфизм, перегрузка операторов, перегрузка функций и пр.) пишутся разными , несовместимыми способами (как левая нога подскажет). Из-за этого использование таких техник из разных языков получается невозможным.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
|