Выполняемый модуль глючит?

Автор alyuev, 03 декабря 2024, 01:15

« назад - далее »

alyuev

Граждане, кто-то может объяснить, почему параметры функции возвращают какую-то лабуду при вызове через переменную ВполняемыйМодуль?

ВыполняемыйМодуль = "";
Текст_Модуля="Функция НашаФормула(П1=1, П2=2, П3=3)
|		Сообщить(""НашаФормула(П1=""+П1+"" П2=""+П2+"" П3=""+П3+"")"");
|КонецФункции";
ВыполняемыйМодуль=СоздатьОбъект("ВыполняемыйМодуль");
ВыполняемыйМодуль.УстановитьМодуль(Текст_Модуля);
ВыполняемыйМодуль.НазначитьКонтекст(Контекст);
ВыполняемыйМодуль.КомпилироватьИВыполнитьМодуль();


ВыполняемыйМодуль.НашаФормула();     //выдало НашаФормула(П1= П2=1 П3=2), ожидалось П1=1 П2=2 П3=3
ВыполняемыйМодуль.НашаФормула(10);   //выдало НашаФормула(П1=10 П2= П3=2), ожидалось П1=10 П2=2 П3=3
ВыполняемыйМодуль.НашаФормула(10,20);//выдало НашаФормула(П1=10 П2=20 П3=), ожидалось П1=10 П2=20 П3=3
ВыполняемыйМодуль.НашаФормула(10,,30);//выдало НашаФормула(П1=10 П2= П3=30), ожидалось П1=10 П2=2 П3=30

Обратите внимание - первый непередаваемый параметр = Пусто, а остальные - смещаются!
И почему не подставилось по-умолчанию?


Djelf

Это не реализовано в ExecuteModule.cpp CExecuteModule::GetParamDefValue
В лучшем случае п1,п2,п3 равны порядковому номеру параметра, в худшем там все перепутано.

alyuev

О... Да... Немного изменил тест и теперь видно, что ставит порядковый номер:

ВыполняемыйМодуль = "";//СпФормул.Получить(Формула);
	Текст_Модуля="Функция НашаФормула(П1=11, П2=22, П3=33)
	|		Сообщить(""НашаФормула(П1=""+П1+"" П2=""+П2+"" П3=""+П3+"")"");
	|КонецФункции";
ВыполняемыйМодуль=СоздатьОбъект("ВыполняемыйМодуль");
ВыполняемыйМодуль.УстановитьМодуль(Текст_Модуля);
ВыполняемыйМодуль.НазначитьКонтекст(Контекст);
ВыполняемыйМодуль.КомпилироватьИВыполнитьМодуль();

ВыполняемыйМодуль.НашаФормула();	  //НашаФормула(П1= П2=1 П3=2)  , ожидалось П1=11 П2=22 П3=33
ВыполняемыйМодуль.НашаФормула(10);    //НашаФормула(П1=10 П2= П3=2) , ожидалось П1=10 П2=22 П3=33
ВыполняемыйМодуль.НашаФормула(10,20); //НашаФормула(П1=10 П2=20 П3=), ожидалось П1=10 П2=20 П3=33
ВыполняемыйМодуль.НашаФормула(10,,30);//НашаФормула(П1=10 П2= П3=30), ожидалось П1=10 П2=22 П3=30

Djelf

Собрать то 1с++ я могу, но я не понимаю как получить значение в контексте функции/процедуры.
Вроде их получают через pModule->EvalExpr(VarInfo.GetName(), val, &masval), masval - штука непонятная, а  val это то что нам нужно. Но вызов этого метода убивает все переменные в функции...
Я этого не понимаю  ;D

ИМХО: Забей на эту тему, лет 15 назад ее надо было поднимать, когда те кто знал и понимал, были еще активны.

Передавай как в снеговике: ПолучитьПараметрыВызоваЧегоТо(), ВызватьЧтоТо(ПараметрыВызова).
Не так лаконично, но и плюсов довольно много.

alyuev

Сейчас-то, конечно, вопрос закрыт - просто указанием в вызове функции всех параметров.

 А на счет этого:
Цитата: Djelf от 03 декабря 2024, 14:44Передавай как в снеговике: ПолучитьПараметрыВызоваЧегоТо(), ВызватьЧтоТо(ПараметрыВызова)

если честно - не понял про что речь. Передавать параметры списком?


АЛьФ

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

Djelf

АЛьФ, у тебя же компилятор есть, вроде как-то ты мне давал точку входа для исследований...
Что и где там по факту вызывается перед CallAsFunc,  CallAsProc?

Этот вопрос, скорее на упражнение ума и разгадывание шарад внутри клюшек.
И то и другое помогает отвлечься от работы...

Не помню, с Классами была такая проблема? Решили?

Djelf

Цитата: alyuev от 03 декабря 2024, 17:58если честно - не понял про что речь. Передавать параметры списком?
Чем угодно - тз, сз, итз, вектором... Времена изменились, за каждый тик процессора особенно бороться не требуется.

АЛьФ

Цитата: Djelf от 04 декабря 2024, 14:37АЛьФ, у тебя же компилятор есть, вроде как-то ты мне давал точку входа для исследований...
Что и где там по факту вызывается перед CallAsFunc,  CallAsProc?

Этот вопрос, скорее на упражнение ума и разгадывание шарад внутри клюшек.
И то и другое помогает отвлечься от работы...

Не помню, с Классами была такая проблема? Решили?

В FormEx Артур вынес получение значений по умолчанию в отдельную процедуру:
void CService::GetModuleMethodParamDefValue( CBLModule * pMod, int iMethodNumber, int iParamNumber, CValue& value)
{
	CCompiledModule* pCompiledModule = pMod->GetInternalData()->pCompiledModule;
	CBLModuleProcVarDescr* pVar = pCompiledModule->ProcArray[iMethodNumber]->VarList[iParamNumber];
	if(pVar->Type2 >= 0)
		value = pCompiledModule->ConstArray[pVar->Type2]->val;
	else
		value.Reset();
}
Но это очень ненадежный метод, т.к. никаких проверок на корректность ссылок там нет.

Djelf

Спасибо!
Есть сомнения в ненадежности, количество параметров определено, выхода за пределы массива быть не должно, с чего ссылки могут побится... ну они и без проверок бывает глючат...
Имхо iMethodNumber надо бы заменить на iRealMethodNumber, как сделано в других классах 1с++, где встречается подобная конструкция.
С некоторыми изменениями код заработал.
icpp 3.2.4.3.bf1 https://cloud.mail.ru/public/2182/cjQXqp43r

--- ./ExecuteModule.cpp	2008-06-07 07:59:05.000000000 +0300
+++ ./ExecuteModule.new.cpp	2024-12-05 06:53:22.000000000 +0300
@@ -278,8 +278,24 @@ int CExecuteModule::GetNParams(int iMeth
 
 int  CExecuteModule::GetParamDefValue(int iMethodNum,int iParamNum,CValue * pDefValue)const
 {
-	if (IsUserMethod(iMethodNum))
-		return TRUE;
+	if (IsUserMethod(iMethodNum)){
+        // https://forum.dorex.pro/index.php?topic=204.msg2722#new
+        // параметры по-умолчанию для процедур и функций
+        //{ Djelf
+        CBLProcInfo ProcInfo;
+        pBLModule->GetProcInfo(GetMethodNumberInUserModule(iMethodNum),ProcInfo);
+        CCompiledModule* pCompiledModule = pBLModule->GetInternalData()->pCompiledModule;
+        CBLModuleProcVarDescr* pVar = pCompiledModule->ProcArray[ProcInfo.GetProcPos()]->VarList[iParamNum];
+        if(pVar->Type2 >= 0){
+            *pDefValue =  pCompiledModule->ConstArray[pVar->Type2]->val;
+            return TRUE;
+        }
+        else {
+            return FALSE;
+        }
+        //return TRUE;
+        //} Djelf
+	}
 
 	if (IDProcThrow == iMethodNum && iParamNum == 1)
     {

АЛьФ

В связи с этой темой вдруг родилась мысль. В 1С ведь параметры по умолчанию могут быть только простых типов - число, строка, дата. Но вот тут "ConstArray[pVar->Type2]->val" хранится тип CValue. Следовательно можно сделать метод типа ВыполняемыйМодуль::ПараметрПоУмолчанию(ИмяФункции, НомерПараметра[, ЗначениеПараметра]), который будет возвращать текущее значение и в случае необходимости устанавливать новое.
Какое широкое поле открывается...
Ведь к выполняемому модулю можно текущий модуль установить. Т.е. устанавливать значения по умолчанию любого типа можно будет для каких угодно модулей.

Злоп

Я как неспециалист скажу:
- понятно что здорово, но здорово непонятно...

Злоп

Типа пример бы, пусть даже нерабочий, но концептуальный

АЛьФ

Цитата: Злоп от 05 декабря 2024, 10:19Типа пример бы, пусть даже нерабочий, но концептуальный

Функция глПолучитьИННФирмы(Фирма = "") Экспорт
    Возврат Фирма.ИНН;
КонецФункции

ВыполняемыйМодуль.ПараметрПоУмолчанию("глПолучитьИННФирмы", 1, глФирма);
Сообщить("ИНН = " + глПолучитьИННФирмы()); // возвращает ИНН из глФирма

alyuev

Цитата: Djelf от 05 декабря 2024, 07:25С некоторыми изменениями код заработал.

Пытаюсь открыть внешний отчет, в котором была ошибка. Отчет не открылся и в Сообщить выдало:

pNewWnd->CreateControl

При повторной попытке открыть этот же отчет выдало то же сообщение и при этом 1С вылетела.