Редактировать: Вы можете получить полный источник здесь: http://pastebin.com/m26693
Снова отредактируйте: я добавил несколько бликов на страницу для вставки. http://pastebin.com/m10f8d239
Я, вероятно, пожалею, что задал такой длинный вопрос, но я озадачен этой ошибкой и мог бы воспользоваться некоторыми рекомендациями. Вам нужно будет запустить этот код (редактировать: больше нет. Я не мог включить весь код - он был усечен), чтобы помочь реально увидеть, что происходит, если вы не Бог или что-то в этом роде, тогда непременно разобраться, не запустив его. На самом деле, я надеюсь, что смогу объяснить это достаточно хорошо, так что в этом нет необходимости, и я прошу прощения, если я этого не сделаю.
Сначала я дам вам вывод. (Изменить: ниже приведен новый вывод)
argc 1 [<__main__.RESULT instance at 0x94f91ec>]
(<__main__.RESULT instance at 0x9371f8c>, <__main__.RESULT instance at 0x94f91ec>)
None
bar
internal error: unknown result type 0
argc 1 [<__main__.RESULT instance at 0x94f92ac>]
(<__main__.RESULT instance at 0x94f91ac>, <__main__.RESULT instance at 0x94f92ac>)
None
bar
internal error: unknown result type 0
argc 1 [<__main__.RESULT instance at 0x94f91ec>]
(<__main__.RESULT instance at 0x94f91ec>,)
String: 'bar'
У нас есть 3 деления на выходе. Обратите внимание, что argc всегда равен 1. В точке, где это печатается, создается список аргументов для передачи плагину (Плагины - это просто команды в интерпретаторе выражений. Большая часть этого кода является интерпретатором выражений.) Список единственное представление экземпляра RESULT, которое следует за argc, является списком аргументов. Следующая строка - это список аргументов, когда он достигает вызываемого метода Python. Обратите внимание, что на этом этапе есть два аргумента. Первый из этих двух - мусор. Второй - то, что я хотел. Однако, как вы можете видеть в строках, начинающихся с «argc 1», этот список аргументов всегда имеет ширину 1 RESULT. Откуда исходит беспризорный аргумент?
Как я уже сказал, на выходе есть 3 деления. Первый дивизион сам по себе класс. Второе подразделение является подклассовым классом. И третье деление вообще не класс / экземпляр. Единственное подразделение, которое выводит то, что я ожидал, это третье. Обратите внимание, что у него есть 1 аргумент-член как до вызова, так и внутри вызова, а последняя строка является предполагаемым выводом. Он просто повторяет / возвращает аргумент "bar".
Есть ли какие-то особенности со списками переменных аргументов, о которых мне следует знать? Я имею в виду следующее:
def foo(result, *argv):
print argv[0]
Я действительно думаю, что ошибка как-то связана с этим, потому что именно отсюда, кажется, происходит мусор - между вызовом и прибытием выполнения в методе.
Редактировать: Хорошо, поэтому они ограничивают размер этих вопросов. :) Я сделаю все возможное, чтобы показать, что происходит. Вот соответствующая часть EvalTree. Обратите внимание, что в этом коде есть только 2 деления. Я испортил этот другой файл и удалил его.
def EvalTree(self, Root):
type = -1
number = 0.0
freeme = 0
if Root.Token == T_NUMBER or Root.Token == T_STRING:
return 0
elif Root.Token == T_VARIABLE:
self.CopyResult(Root.Result, Root.Variable.value)
return 0
elif Root.Token == T_FUNCTION:
argc = Root.Children
param = resizeList([], argc, RESULT)
print "argc", argc
for i in range(argc):
self.EvalTree(Root.Child[i])
param[i] = Root.Child[i].Result
self.DelResult(Root.Result)
Root.Function.func(Root.Result, *param) # I should have never ever programmed Lua ever.
return 0
Вот класс плагина.
class Foo:
def __init__(self, visitor):
visitor.AddFunction("foo", -1, self.foo)
def foo(self, result, *argv):
print argv
Вот где все это выполняется.
if __name__ == "__main__":
evaluator = Evaluator()
expression = "foo2('bar')"
#expression = "uptime('test')"
evaluator.SetVariableString("test", "Foo")
def func(self, result, *arg1):
print arg1
evaluator.SetResult(result, R_STRING, evaluator.R2S(arg1[0]))
evaluator.AddFunction('foo2', -1, func)
result = RESULT(0, 0, 0, None)
tree = evaluator.Compile(expression)
if tree != -1:
evaluator.Eval(tree, result)
if result.type == R_NUMBER:
print "Number: %g" % (evaluator.R2N(result))
elif result.type == R_STRING:
print "String: '%s'" % (result.string) #(evaluator.R2S(result))
elif result.type == (R_NUMBER | R_STRING):
print "String: '%s' Number: (%g)" % (evaluator.R2S(result), evaluator.R2N(result))
else:
print "internal error: unknown result type %d" % (result.type)
expression = "foo('test')"
result = RESULT(0, 0, 0, None)
tree = evaluator.Compile(expression)
if tree != -1:
evaluator.Eval(tree, result)
if result.type == R_NUMBER:
print "Number: %g" % (evaluator.R2N(result))
elif result.type == R_STRING:
print "String: '%s'" % (result.string) #(evaluator.R2S(result))
elif result.type == (R_NUMBER | R_STRING):
print "String: '%s' Number: (%g)" % (evaluator.R2S(result), evaluator.R2N(result))
else:
print "internal error: unknown result type %d" % (result.type)
Это новый вывод:
argc 1
(<__main__.RESULT instance at 0x9ffcf4c>,)
String: 'bar'
argc 1
(<__main__.RESULT instance at 0xa0030cc>, <__main__.RESULT instance at 0xa0030ec>)
internal error: unknown result type 0