Что нового

Проверить существование функции и количество аргументов.

idbehold

Новичок
Сообщения
42
Репутация
4
Всем привет! Возникла необходимость проверять существование функции (название функции содержится в строке)
Если функция существует - узнать количество аргументов, которые эта функция принимает.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Код:
$sStr = 'Func MyFunc($vArg1, $vArg2)'

$aTest = StringRegExp($sStr, '(?i)Func (\w+)\s*\(([^\)]*)\)', 3)
$aArgs = StringRegExp($aTest[1], '(\$\w+)', 3)

$sArgs = ''

For $i = 0 To UBound($aArgs)-1
	$sArgs &= $aArgs[$i] & @CRLF
Next

MsgBox(64, '', UBound($aArgs) & ' Args in func ' & $aTest[0] & '():' & @CRLF & @CRLF & $sArgs)
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
Надо ещё удалить значения назначенные переменным по умолчанию, они могут содержать строку совпадающую с именем переменной или скобку ")", хотя это редкость.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
AZJIO [?]
Надо ещё удалить значения назначенные переменным по умолчанию, они могут содержать строку совпадающую с именем переменной или скобку ")"
Тогда вот такой вариант:

Код:
#include <Array.au3>

$sAu3Str = 'Func MyFunc($vArg1 = "Str()", $vArg2, $vArg3 = Default, $vArg4 = ''$vVar'')'

$aData = _Au3StringGetFuncs($sAu3Str)
_ArrayDisplay($aData)

Func _Au3StringGetFuncs($sString)
	$aTest = StringRegExp($sString, '(?i)Func (\w+)\s*\((.*)\)', 3)
	Local $aRet[UBound($aTest)][4]
	
	For $i = 1 To UBound($aTest)-1 Step 2
		$sFunc = $aTest[$i-1]
		$aArgs = StringRegExp($aTest[$i], '(\$\w+)(?:\s*=\s*("[^"]*"|''[^'']*''|[^,\)]+))?', 3)
		$iUbnd = UBound($aArgs)
		
		$sArgs = ''
		$sDefs = ''
		$iCount = 0
		
		For $j = 0 To $iUbnd-1
			If StringLeft($aArgs[$j], 1) = '$' Then
				$sArgs &= $aArgs[$j] & '|'
				$iCount += 1
				
				If $j < $iUbnd-1 And StringLeft($aArgs[$j+1], 1) = '$' Then
					$sDefs &= '|'
				EndIf
			Else
				$sDefs &= $aArgs[$j] & '|'
			EndIf
		Next
		
		$aRet[0][0] += 1
		$aRet[$aRet[0][0]][0] = $sFunc
		$aRet[$aRet[0][0]][1] = StringTrimRight($sArgs, 1)
		$aRet[$aRet[0][0]][2] = StringTrimRight($sDefs, 1)
		$aRet[$aRet[0][0]][3] = $iCount
	Next
	
	ReDim $aRet[$aRet[0][0]+1][4]
	Return $aRet
EndFunc
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
Можно удалить текстовые строки
Код:
$sString = StringRegExpReplace($sString, '(["'']).*?\1', '') ; удаление текстовых строк

А потом получить переменные.

Непонятны входные данные.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
AZJIO [?]
Можно удалить текстовые строки
Ну это если простой вариант, т.е если нужен только подсчёт аргументов. Кстати в качестве значении аргументов может быть не только строка ;).
Мой пример выше позволяет получить в массив все данные о функции:
Код:
[N][0] - Имя функции
[N][1] - Аргументы (разделены символом |).
[N][2] - Значения аргументов по умолчанию (разделены символом |), если аргумента нет, добавляется пустой символ разделения.
[N][3] - Число аргументов.
 
Автор
idbehold

idbehold

Новичок
Сообщения
42
Репутация
4
Ой ребята... развели вы тут и я не смог вовремя направить вас в нужную сторону - только сейчас до форума добрался.
Спасибо, что откликнулись, код хороший, но мне не нужно получать название функции из строки.

Я хочу проверить, есть ли в списке определенных функций функция с таким-то названием.
То есть, если функция была описана в коде или это встроенная функция autoit - проверка должна вернуть true.
Мне это нужно для того чтобы я мог выполнить Execute не опасаясь, что туда попадет нерабочий код.

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

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Я бы сделал не проверку наличия функции (насколько я знаю такой проверки вроде нету), а внутри функции организовал бы код блоками и проверял наличие блока, например так:
Код:
Local $Func = "Atack"
Local $var = MyFunc($Func, "GetBlockInfo")
If Not @error Then
   MsgBox(0,$Func,$var)
   $var = MyFunc($Func, "Mob", "With Skill")
   If Not @error Then
	  MsgBox(0,$Func,"Execution finished")
   ElseIf @error = 100500 Then
	  MsgBox(0,$Func,$var)
   EndIf
Else
   MsgBox(0,$Func,"No such function")
EndIf

$Func = "Defence"
$var = MyFunc($Func, "GetBlockInfo")
If Not @error Then
   MsgBox(0,$Func,$var)
   $var = MyFunc($Func, "Character1", "With Armor", "With Spell")
   If Not @error Then
	  MsgBox(0,$Func,"Execution finished")
   ElseIf @error = 100500 Then
	  MsgBox(0,$Func,$var)
   EndIf
Else
   MsgBox(0,$Func,"No such function")
EndIf

$Func = "Looot"
$var = MyFunc($Func, "GetBlockInfo")
If Not @error Then
   MsgBox(0,$Func,$var)
   $var = MyFunc($Func, "Character1", "With Armor", "With Spell")
   If Not @error Then
	  MsgBox(0,$Func,"Execution finished")
   ElseIf @error = 100500 Then
	  MsgBox(0,$Func,$var)
   EndIf
Else
   MsgBox(0,$Func,"No such function")
EndIf




Func MyFunc($Block, $Param1="NULL", $Param2="NULL", $Param3="NULL", $Param4="NULL")
   Select
	  Case $Block= "Atack"
		 Local $BlockInfo = "Using 2 Params"
		 If $Param1 = "GetBlockInfo" Then Return $BlockInfo
		 SetError(100500)
		 If $Param1 = "NULL" Or $Param2="NULL" Then Return $Block&": Incorrect number of parameters in function call"
		 #Region - Область исполняемого кода блока "Atack"
			MsgBox(0,"Execution "&$Block, $Param1&@CR&$Param2)
		 #EndRegion - Область исполняемого кода блока "Atack"
	  Case $Block= "Defence"
		 Local $BlockInfo = "Using 4 Params"
		 If $Param1 = "GetBlockInfo" Then Return $BlockInfo
		 SetError(100500)
		 If $Param1 = "NULL" Or $Param2="NULL" Or $Param3="NULL" Or $Param4="NULL" Then Return $Block&": Incorrect number of parameters in function call"
		 #Region - Область исполняемого кода блока "Defence"
			MsgBox(0,"Execution "&$Block, $Param1&@CR&$Param2&@CR&$Param3&@CR&$Param4)
		 #EndRegion - Область исполняемого кода блока "Defence"
	  Case $Block = "Loot"
		 Local $BlockInfo = "Using 1 Params"
		 If $Param1 = "GetBlockInfo" Then Return $BlockInfo
		 SetError(100500)
		 If $Param1 = "NULL" Then Return $Block&": Incorrect number of parameters in function call"
		 #Region - Область исполняемого кода блока "Defence"
			MsgBox(0,"Execution "&$Block, $Param1&@CR&$Param2&@CR&$Param3&@CR&$Param4)
		 #EndRegion - Область исполняемого кода блока "Defence"
	  Case Else
		 SetError(1)
		 Return False
   EndSelect
EndFunc



Добавлено:
Сообщение автоматически объединено:

У меня например имена блоков которые можно использовать клиенту хранятся на сервере. После успешной авторизации клиент получает набор функций которые он должен использовать, различные настройки и тд и тп и только после этого начинает работу.

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

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
idbehold [?]
Я хочу проверить, есть ли в списке определенных функций функция с таким-то названием.
Что за список, откуда он берётся?
Если с файла, то не вижу никакой проблемы использования функции выше.

Мне это нужно для того чтобы я мог выполнить Execute не опасаясь, что туда попадет нерабочий код.
А в чём собственно опасность, можно же проверять что возвращает Execute.
 
Автор
idbehold

idbehold

Новичок
Сообщения
42
Репутация
4
Подводя итоги темы - стандартными средствами автоит проверить существование функции нельзя.

У меня например имена блоков которые можно использовать клиенту хранятся на сервере. После успешной авторизации клиент получает набор функций которые он должен использовать, различные настройки и тд и тп и только после этого начинает работу.
Да, и мне сейчас приходится делать примерно так же. Получается, что я разрешаю клиенту выполнять те функции которые разрешил.
А я бы хотел выполнять все что есть, не описывая их дополнительно нигде.

А в чём собственно опасность, можно же проверять что возвращает Execute.
Да, надо будет подумать над этим.

Ладно, с проблемой разберусь, думаю.
Спасибо.
 
Верх