Граждане, кто-то может объяснить, почему параметры функции возвращают какую-то лабуду при вызове через переменную ВполняемыйМодуль?
ВыполняемыйМодуль = "";
Текст_Модуля="Функция НашаФормула(П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
Обратите внимание - первый непередаваемый параметр = Пусто, а остальные - смещаются!
И почему не подставилось по-умолчанию?
Это не реализовано в ExecuteModule.cpp CExecuteModule::GetParamDefValue
В лучшем случае п1,п2,п3 равны порядковому номеру параметра, в худшем там все перепутано.
О... Да... Немного изменил тест и теперь видно, что ставит порядковый номер:
ВыполняемыйМодуль = "";//СпФормул.Получить(Формула);
Текст_Модуля="Функция НашаФормула(П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
Собрать то 1с++ я могу, но я не понимаю как получить значение в контексте функции/процедуры.
Вроде их получают через pModule->EvalExpr(VarInfo.GetName(), val, &masval), masval - штука непонятная, а val это то что нам нужно. Но вызов этого метода убивает все переменные в функции...
Я этого не понимаю ;D
ИМХО: Забей на эту тему, лет 15 назад ее надо было поднимать, когда те кто знал и понимал, были еще активны.
Передавай как в снеговике: ПолучитьПараметрыВызоваЧегоТо(), ВызватьЧтоТо(ПараметрыВызова).
Не так лаконично, но и плюсов довольно много.
Сейчас-то, конечно, вопрос закрыт - просто указанием в вызове функции всех параметров.
А на счет этого:
Цитата: Djelf от 03 декабря 2024, 14:44Передавай как в снеговике: ПолучитьПараметрыВызоваЧегоТо(), ВызватьЧтоТо(ПараметрыВызова)
если честно - не понял про что речь. Передавать параметры списком?
С получением значений по умолчанию для функций и процедур в 1С полный мрак. Пытался с этим вопросом разбираться. Вроде как получилось, но уж очень кривой код получается. Функций экспортных нет для получения нужного, приходится через свойства объектов шагать. А это очень ненадежно.
АЛьФ, у тебя же компилятор есть, вроде как-то ты мне давал точку входа для исследований...
Что и где там по факту вызывается перед CallAsFunc, CallAsProc?
Этот вопрос, скорее на упражнение ума и разгадывание шарад внутри клюшек.
И то и другое помогает отвлечься от работы...
Не помню, с Классами была такая проблема? Решили?
Цитата: 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();
}
Но это очень ненадежный метод, т.к. никаких проверок на корректность ссылок там нет.
Спасибо!
Есть сомнения в ненадежности, количество параметров определено, выхода за пределы массива быть не должно, с чего ссылки могут побится... ну они и без проверок бывает глючат...
Имхо 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, глФирма);
Сообщить("ИНН = " + глПолучитьИННФирмы()); // возвращает ИНН из глФирма
Цитата: Djelf от 05 декабря 2024, 07:25С некоторыми изменениями код заработал.
Пытаюсь открыть внешний отчет, в котором была ошибка. Отчет не открылся и в Сообщить выдало:
pNewWnd->CreateControl
При повторной попытке открыть этот же отчет выдало то же сообщение и при этом 1С вылетела.
Цитата: АЛьФ от 05 декабря 2024, 09:03В связи с этой темой вдруг родилась мысль. В 1С ведь параметры по умолчанию могут быть только простых типов - число, строка, дата. Но вот тут "ConstArray[pVar->Type2]->val" хранится тип CValue. Следовательно можно сделать метод типа ВыполняемыйМодуль::ПараметрПоУмолчанию(ИмяФункции, НомерПараметра[, ЗначениеПараметра]), который будет возвращать текущее значение и в случае необходимости устанавливать новое.
Какое широкое поле открывается...
Ведь к выполняемому модулю можно текущий модуль установить. Т.е. устанавливать значения по умолчанию любого типа можно будет для каких угодно модулей.
Тестовая https://cloud.mail.ru/public/nytf/oEhaAk494
Добавлен метод
ВыполняемыйМодуль::ПараметрПоУмолчанию(ИмяПроцедурыИлиФункции, ИмяПараметра,ЗначениеПараметра)
Исключения при отсутствии в модуле ИмяПроцедурыИлиФункции, ИмяПараметра в найденной.
Возвращает старое значение параметра.
Но фокус не не удался, ТипЗначенияСтр в ВМ выводит первоначатьный тип, поэтому засунуть туда тз вместо числа не получается - значение получается нулевое.
Цитата: alyuev от 05 декабря 2024, 12:03Цитата: Djelf от 05 декабря 2024, 07:25С некоторыми изменениями код заработал.
Пытаюсь открыть внешний отчет, в котором была ошибка. Отчет не открылся и в Сообщить выдало:
pNewWnd->CreateControl
При повторной попытке открыть этот же отчет выдало то же сообщение и при этом 1С вылетела.
Вот поэтому я и не хотел ничего изменять в 1с++, у меня вроде сборка на всем моих данных работает, кто его знает на чем оно у тебя вылетело и как это повторить.
А есть где-то твоя сборка без последней правки? Я бы просто проверил твою компиляцию.
Цитата: Djelf от 05 декабря 2024, 12:10Но фокус не не удался, ТипЗначенияСтр в ВМ выводит первоначатьный тип, поэтому засунуть туда тз вместо числа не получается - значение получается нулевое.
Подозреваю, что надо делать сначала Reset переменной "pCompiledModule->ConstArray[pVar->Type2]->val".
Цитата: АЛьФ от 05 декабря 2024, 12:31Цитата: Djelf от 05 декабря 2024, 12:10Но фокус не не удался, ТипЗначенияСтр в ВМ выводит первоначатьный тип, поэтому засунуть туда тз вместо числа не получается - значение получается нулевое.
Подозреваю, что надо делать сначала Reset переменной "pCompiledModule->ConstArray[pVar->Type2]->val".
Сдалал. Не помогло, может тип в пи-коде зашивается.
upd: тип зашивается в pVar->Type2, ща мы и его поправим...
Цитата: alyuev от 05 декабря 2024, 12:25А есть где-то твоя сборка без последней правки? Я бы просто проверил твою компиляцию.
Закоментировал код получения параметров по-умолчанию https://cloud.mail.ru/public/J3Sd/Wdio9FM5W
Не, pVar->Type2 это позиция в параметре.
pVar->Type чёрт его знает, она всегда = 3
Тип может где-то еще зашит, но я склоняюсь к пи-коду.
Пока работает как-то так:
ТекстМодуля="Функция ХтоЭто(П1=""Петя"") Возврат П1; КонецФункции
НовыйПараметр = "Вася";
СтарыйПараметр = ВМ.УстановитьПараметрПоУмолчанию("ХтоЭто ","П1",НовыйПараметр);
Зачем? Даже не представляю...
Проще же сделать Функция Универсал(ВходящиеПарматры,ИсходящиеПараметры)
Так сделано в КД2, это разумно и не напряжно.
P.S. КД2 я считаю топом эволюции КД (слегка дописывал, для поддержки итз и т.п.), а КД3 это вырви мосх и то что она работает, это не значит что она удобнее.
Что очень важно: при SetParamDefValue ProcInfo надо заполнять
pBLModule->GetProcInfo(iMethodNum,ProcInfo);
а при GetParamDefValue
pBLModule->GetProcInfo(GetMethodNumberInUserModule(iMethodNum),ProcInfo);
Оставляю как заметку, не вылететь в космос тут сложно..
Цитата: Djelf от 05 декабря 2024, 13:52Цитата: alyuev от 05 декабря 2024, 12:25А есть где-то твоя сборка без последней правки? Я бы просто проверил твою компиляцию.
Закоментировал код получения параметров по-умолчанию https://cloud.mail.ru/public/J3Sd/Wdio9FM5W
Та же ошибка и также падает.
А что такое КД2/КД3? Комплексная...?
Цитата: alyuev от 05 декабря 2024, 16:01А что такое КД2/КД3? Комплексная...?
Конфа Конвертация Данных
IMHO: написана инопланетянами
Цитата: Djelf от 05 декабря 2024, 12:14у меня вроде сборка на всем моих данных работает
А что-нибудь исправлено/улучшено по сравнению с оригиналом?
Только то что в этой теме.
Если я правильно понял о чем в этом топике речь...
Цитата: Djelf от 05 декабря 2024, 15:03Не, pVar->Type2 это позиция в параметре.
pVar->Type чёрт его знает, она всегда = 3
Тип может где-то еще зашит, но я склоняюсь к пи-коду.
Тип любой переменной в т.ч. и параметра хранится в CValue
pVar->Type - это CProcVarInfo::m_Flags (см.ниже)
т.е.
3 - входной параметр передаваемый по значениюclass CProcVarInfo
{
public:
CString m_Name; //04h
int m_ArraySize; //08h
BOOL m_IsExport; //0Ch
int m_Flags; //10h // &1==0 - Знач , &2==1 - in-параметр
int m_ConstInfoIndex; //14h //значение по-умолчанию
public:
virtual ~CProcVarInfo(void);
virtual LPCSTR GetName(void);
};