გარე კომპონენტის ტექნოლოგია (). გარე კომპონენტების ტექნოლოგია () გარე კომპონენტები "1C: Enterprise"

ანსმირნოვი 2013 წლის 22 აგვისტო, 14:12 საათი

გარე კომპონენტები 1C-ში 8.2

  • პროგრამირება,
  • C++
  • სახელმძღვანელო

შესავალი

ეს სტატია იძლევა იდეას, თუ როგორ მუშაობს გარე კომპონენტები 1C: Enterprise სისტემაში.
ნაჩვენები იქნება გარე კომპონენტის შემუშავების პროცესი 1C: Enterprise სისტემის ვერსია 8.2, რომელიც მუშაობს OS-ით. Windows ოჯახითან ფაილის ვერსიამუშაობა. ეს ვარიანტი გამოიყენება მცირე ბიზნესისთვის განკუთვნილი გადაწყვეტილებების უმეტესობაში. VK განხორციელდება C++ პროგრამირების ენაზე.

გარე კომპონენტები "1C: Enterprise"

"1C: Enterprise" არის გაფართოებადი სისტემა. გაფართოებისთვის ფუნქციონირებასისტემა იყენებს გარე კომპონენტებს (EC). დეველოპერის თვალსაზრისით, VC არის გარე ობიექტი, რომელსაც აქვს თვისებები და მეთოდები და ასევე შეუძლია შექმნას მოვლენები 1C: Enterprise სისტემის მიერ დამუშავებისთვის.
გარე კომპონენტები შეიძლება გამოყენებულ იქნას პრობლემების კლასის გადასაჭრელად, რომელთა დანერგვა რთული ან თუნდაც შეუძლებელია პროგრამირების ენაში ჩაშენებული 1C: Enterprise. კერძოდ, ეს კლასი მოიცავს დავალებებს, რომლებიც მოითხოვს დაბალი დონის ურთიერთქმედებას ოპერაციული სისტემამაგალითად, კონკრეტულ აღჭურვილობასთან მუშაობა.
1C: Enterprise სისტემა იყენებს ორ ტექნოლოგიას გარე კომპონენტების შესაქმნელად:
  • Native API-ის გამოყენებით
  • COM ტექნოლოგიის გამოყენებით
მოცემული შეზღუდვების გათვალისწინებით, განსხვავება ორ ზემოთხსენებულ ტექნოლოგიას შორის უმნიშვნელოა, ამიტომ განვიხილავთ ვიდეო თამაშების განვითარებას Native API-ის გამოყენებით. საჭიროების შემთხვევაში, განხორციელებული განვითარება შეიძლება გამოყენებულ იქნას კომპიუტერული პროგრამული უზრუნველყოფის შემუშავებაზე COM ტექნოლოგიის გამოყენებით და ასევე, მცირე ცვლილებებით, გამოიყენოს 1C: Enterprise სისტემაში სხვა სამუშაო ვარიანტებით, გარდა ფაილის რეჟიმიმუშაობა.
VK სტრუქტურა
1C: Enterprise სისტემის გარე კომპონენტი წარმოდგენილია DLL ბიბლიოთეკის სახით. ბიბლიოთეკის კოდი აღწერს შთამომავალ კლასს IComponentBase. შექმნილმა კლასმა უნდა განსაზღვროს მეთოდები, რომლებიც პასუხისმგებელნი არიან გარე კომპონენტის ფუნქციების განხორციელებაზე. გადაჭარბებული მეთოდები უფრო დეტალურად იქნება აღწერილი ქვემოთ, როგორც მასალა წარმოდგენილია.

დემო VK-ის გაშვება

ამოცანა:
  1. შეაგროვეთ გარე კომპონენტი, რომელიც მიეწოდება ITS გამოწერას და გამიზნულია გარე კომპონენტის მექანიზმის ძირითადი შესაძლებლობების დემონსტრირებისთვის 1C-ში
  2. შეაერთეთ დემო კომპონენტი 1C კონფიგურაციასთან
  3. დარწმუნდით, რომ დეკლარირებული ფუნქციები მუშაობს სწორად
კომპილაცია
დემო VK მდებარეობს ITS სააბონენტო დისკზე "/VNCOMP82/example/NativeAPI" დირექტორიაში.
დემო VK-ის ასაშენებლად ჩვენ გამოვიყენებთ Microsoft Visual Studio 2008. ამ პროდუქტის სხვა ვერსიებს არ აქვს ვიზუალური სტუდიის პროექტის ფორმატის მხარდაჭერა.


გახსენით AddInNative პროექტი. პროექტის პარამეტრებში ჩვენ ვდებთ დირექტორიას პროექტის ასაშენებლად საჭირო სათაურის ფაილებით. ნაგულისხმევად, ისინი განლაგებულია დირექტორიაში ITS დისკზე /VNCOMP82/შეიცავს.
აშენების შედეგი არის ფაილი /bind/AddInNative.dll. ეს არის შედგენილი ბიბლიოთეკა 1C კონფიგურაციასთან დასაკავშირებლად.
VK-ის დაკავშირება 1C კონფიგურაციასთან
მოდით შევქმნათ ცარიელი 1C კონფიგურაცია.
ქვემოთ მოცემულია მოდულის კოდი მართული აპლიკაცია.
ცვლადი DemoComp; პროცედურა სისტემის დაწყებისას() გარე კომპონენტის დაკავშირება("...\bind\AddInNative.dll", "DemoVK", External Component Type.Native); DemoComp = New ("AddIn.DemoVK.AddInNativeExtension"); დასრულების პროცედურა
თუ 1C კონფიგურაციის დაწყებისას შეცდომა არ დაფიქსირდა, მაშინ VK წარმატებით იყო დაკავშირებული.
ზემოაღნიშნული კოდის შესრულების შედეგად, ობიექტი ჩნდება კონფიგურაციის გლობალურ ხილვადობაში. DemoComp, რომელსაც აქვს თვისებები და მეთოდები, რომლებიც განსაზღვრულია გარე კომპონენტის კოდში.
ჩაშენებული ფუნქციონირების დემონსტრირება
მოდით შევამოწმოთ VK-ის დემო ფუნქციონირება. ამისათვის შევეცადოთ დავაყენოთ და წავიკითხოთ ზოგიერთი თვისება, მოვუწოდებთ VK მეთოდებს, ასევე მივიღოთ და დავამუშავოთ VK შეტყობინება.
ITS დისკზე მოწოდებულ დოკუმენტაციაში მითითებულია დემო VC-ის შემდეგი ფუნქციონირება:
  1. კომპონენტის ობიექტის მდგომარეობის მართვა
    მეთოდები: Ჩართვა, Გამორთვა
    Თვისებები: შედის
  2. ტაიმერის მართვა
    ყოველ წამს კომპონენტი აგზავნის შეტყობინებას 1C: Enterprise სისტემა პარამეტრებით Კომპონენტი, ტაიმერიდა სისტემური საათის მრიცხველი ხაზი.
    მეთოდები: StartTimer, StopTimer
    Თვისებები: არის ტაიმერი
  3. მეთოდი ShowInStatusLine, რომელიც აჩვენებს ტექსტს სტატუსის ზოლში ამ მეთოდით y როგორც პარამეტრები
  4. მეთოდი ატვირთეთ სურათი. იტვირთება სურათი მითითებული ფაილიდა გადასცემს მას 1C: Enterprise სისტემას ბინარული მონაცემების სახით.
მოდით დავრწმუნდეთ, რომ ეს ფუნქციები მუშაობს. ამისათვის გაუშვით შემდეგი კოდი:
ცვლადი DemoComp; პროცედურა როდესაც სისტემა იწყება() ConnectExternalComponent(...); DemoComp = New ("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); ანგარიში (DemoComp.Enabled); DemoComp.Enable(); ანგარიში (DemoComp.Enabled); DemoComp.StartTimer(); პროცედურის დასრულების პროცედურა გარე მოვლენის დამუშავება(წყარო, მოვლენა, მონაცემები) ანგარიში (წყარო + " " + მოვლენა + " " + მონაცემები); დასრულების პროცედურა
კონფიგურაციის გაშვების შედეგი ნაჩვენებია სურათზე


"შეტყობინებების" პანელი აჩვენებს მეთოდის ზარების შედეგებს DemoComp.Disable()და Demo.Comp.Enable(). იმავე პანელში მომდევნო სტრიქონები შეიცავს VK-დან მიღებული შეტყობინებების დამუშავების შედეგებს - წყარო, ღონისძიებადა მონაცემებიშესაბამისად.

მორგებული გარე კომპონენტის სახელი

ამოცანა: შეცვალეთ გარე კომპონენტის სახელი თვითნებურად.
წინა განყოფილებაში გამოყენებული იყო იდენტიფიკატორი AddInNative Extension, რომლის მნიშვნელობა არ იყო ახსნილი. Ამ შემთხვევაში AddInNative Extension- ეს არის გაფართოების სახელი.
VK კოდი განსაზღვრავს მეთოდს RegisterExtensionAs, დააბრუნებს სახელს 1C: Enterprise სისტემაში, რომელიც აუცილებელია სისტემაში VK-ის შემდგომი რეგისტრაციისთვის. რეკომენდებულია იდენტიფიკატორის მითითება, რომელიც გარკვეულწილად ავლენს გარე კომპონენტის არსს.
აქ არის მეთოდის სრული კოდი RegisterExtensionAsგაფართოების სახელით შეიცვალა:
bool caddinnative :: registerextensionas (wchar_t ** wsextensionName) (wchar_t* wsextension = l "somename"; int iActualsize = :: wcSlen (wsextension) + 1; wchar_t* dest = 0; if (m_imemory) (if (m_iMemory-> ტოტმემი. ((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, iActualSize) დააბრუნებს false;
მოცემულ მაგალითში VK სახელი შეიცვალა SomeName. შემდეგ VK-ს დაკავშირებისას უნდა მიუთითოთ ახალი სახელი:
DemoComp = New ("AddIn.DemoVK.SomeName");

VK თვისებების სიის გაფართოება

ამოცანა:
  1. შეისწავლეთ VK თვისებების განხორციელება
  2. დაამატეთ სტრიქონის ტიპის წაკითხვის/ჩაწერის თვისება
  3. დაამატეთ წაკითხვის/ჩაწერის სტრიქონის თვისება, რომელიც ინახავს ბოლო თვისებების ნაკრების მონაცემთა ტიპს. ქონების ღირებულების დაყენებისას არანაირი ქმედება არ განხორციელდება

შექმნილი კომპონენტის თვისებების დასადგენად, დეველოპერმა უნდა განახორციელოს შემდეგი მეთოდები AddInNative.cpp ბიბლიოთეკის კოდში:
GetNProps
აბრუნებს ამ გაფართოების თვისებების რაოდენობას, 0 თუ არ არის თვისებები
FindProp
აბრუნებს იმ ქონების სერიულ ნომერს, რომლის სახელიც გადაცემულია პარამეტრებში
GetPropName
აბრუნებს ქონების სახელს მისი სერიული ნომრით და გავლილი ენის იდენტიფიკატორით
GetPropVal
აბრუნებს ქონების ღირებულებას მითითებული რიგითი ნომრით
SetPropVal
ადგენს ქონების ღირებულებას მითითებული რიგითი ნომრით
IsPropReadable
აბრუნებს ქონების წაკითხვის დროშას მითითებული თანმიმდევრული ნომრით
IsPropWritable
აბრუნებს ქონების ჩაწერადობის დროშას მითითებული თანმიმდევრული ნომრით


განვიხილოთ ზემოთ მოყვანილი კლასის მეთოდების განხორციელება CAddInNative.
დემო VC-ში განსაზღვრულია 2 თვისება: შედისდა არის ტაიმერი (ჩართულიადა IsTimerPresent).
ბიბლიოთეკის კოდის გლობალურ ასპექტში განსაზღვრულია ორი მასივი:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"ჩართულია", L"არსებობს ტაიმერი");
რომლებშიც ინახება რუსული და ინგლისური ქონების სახელები. სათაურის ფაილში AddInNative.hჩამოთვლა განისაზღვრება:
enum Props (ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // ყოველთვის ბოლო);
ePropIsEnabledდა ePropIsTimerPresent 0 და 1 მნიშვნელობების შესაბამისად, გამოიყენება თვისებების სერიული ნომრების მნიშვნელოვანი იდენტიფიკატორებით ჩანაცვლებისთვის. ePropLast, რომელსაც აქვს 2 მნიშვნელობა, გამოიყენება თვისებების რაოდენობის მისაღებად (GetNProps მეთოდის გამოყენებით). ეს სახელები გამოიყენება მხოლოდ კომპონენტის კოდის ფარგლებში და არ არის ხელმისაწვდომი გარედან.
FindProp და GetPropName მეთოდები ახორციელებს მასივის ძიებას g_PropNamesდა g_PropNamesRu.
ბიბლიოთეკის მოდულში ველების მნიშვნელობების შესანახად, CAddInNative კლასს აქვს თვისებები, რომლებიც ინახავს კომპონენტის თვისებების მნიშვნელობას. მეთოდები GetPropValდა SetPropValდააბრუნეთ და დააყენეთ ამ თვისებების მნიშვნელობა.
მეთოდები IsPropReadableდა IsPropWritableდა დაბრუნდი მართალიაან ყალბი, აპლიკაციის ლოგიკის შესაბამისად ქონების გავლილი რიგითი ნომრის მიხედვით.
მორგებული საკუთრების დასამატებლად საჭიროა:

  1. დაამატეთ მასივებს დამატების საკუთრების სახელი g_PropNamesდა g_PropNamesRu(ფაილი AddInNative.cpp)
  2. ჩამოთვლა რეკვიზიტები(ფაილი AddInNative.h) ადრე ePropLastდაამატეთ სახელი, რომელიც ცალსახად განსაზღვრავს დამატებულ ქონებას
  3. მეხსიერების ორგანიზება ქონების მნიშვნელობების შესანახად (შექმენით მოდულის კომპონენტის ველები, რომლებიც ინახავს შესაბამის მნიშვნელობებს)
  4. შეიტანეთ ცვლილებები მეთოდებში GetPropValდა SetPropValწინა საფეხურზე გამოყოფილ მეხსიერებასთან ურთიერთობისთვის
  5. განაცხადის ლოგიკის შესაბამისად შეიტანეთ ცვლილებები მეთოდებში IsPropReadableდა IsPropWritable
1, 2, 5 პუნქტებს განმარტება არ სჭირდება. ამ ნაბიჯების განხორციელების დეტალები შეგიძლიათ იხილოთ სტატიის დანართის შესწავლით.
მოდით მივცეთ სახელები ტესტის თვისებებს ტესტიდა აკრიფეთ Checkშესაბამისად. შემდეგ, პირველი ნაბიჯის შედეგად, ჩვენ გვაქვს:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L"ჩართულია", L"არსებობს ტაიმერი", L"ტესტი", L"ტიპის შემოწმება");
Გადაცემა რეკვიზიტებიასე გამოიყურება:
enum Props (ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // ყოველთვის ბოლო);
კოდის საგრძნობლად გასამარტივებლად, ჩვენ გამოვიყენებთ STL C++-ს. კერძოდ, სიმებიანი მუშაობისთვის WCHAR, დავაკავშიროთ ბიბლიოთეკა სტრიქონი.
მეთოდის მნიშვნელობის შესანახად ტესტი, განვსაზღვრავთ კლასში CAddInNativeკერძო სფეროს ფარგლებში:
სიმებიანი ტესტი1;
სტრიქონის პარამეტრების გადასატანად 1C: Enterprise და გარე კომპონენტებს შორის, გამოიყენება 1C: Enterprise მეხსიერების მენეჯერი. მოდით უფრო ახლოს მივხედოთ მის შემოქმედებას. ფუნქციები გამოიყენება მეხსიერების გამოყოფისა და გასათავისუფლებლად AllocMemoryდა თავისუფალი მეხსიერებაფაილში განსაზღვრული ImemoryManager.h. საჭიროების შემთხვევაში, გადაიტანეთ 1C: Enterprise სისტემაში სიმებიანი პარამეტრი, გარე კომპონენტმა უნდა გამოყოს მისთვის მეხსიერება ფუნქციის გამოძახებით AllocMemory. მისი პროტოტიპი ასე გამოიყურება:
ვირტუალური bool ADDIN_API AllocMemory (void** pMemory, ხელმოუწერელი გრძელი ulCountByte) = 0;
სად p მეხსიერება- მაჩვენებლის მისამართი, რომელშიც განთავსდება გამოყოფილი მეხსიერების არეალის მისამართი,
ulCountByte- გამოყოფილი მეხსიერების არეალის ზომა.
სტრიქონისთვის მეხსიერების განაწილების მაგალითი:
WCHAR_T *t1 = NULL, *ტესტი = L"TEST_STRING"; int iActualSize = wcslen(test1)+1; m_iMemory->AllocMemory((void**)&t1, iActualSize * sizeof(WCHAR_T)); ::convToShortWchar(&t1, test1, iActualSize);
სიმებიანი მონაცემთა ტიპებთან მუშაობის მოხერხებულობისთვის, ჩვენ აღვწერთ ფუნქციას wstring_to_p. ის პარამეტრად იღებს wstring სტრიქონს. ფუნქციის შედეგი არის შევსებული სტრუქტურა tVariant. ფუნქციის კოდი:
bool CAddInNative::wstring_to_p(std::wstring str, tVariant* val) (char* t1; TV_VT(val) = VTYPE_PWSTR; m_iMemory-> AllocMemory((void**)&t1, (str.length()+1) sizeof(WCHAR_T)); დაუბრუნე სიმართლე)
შემდეგ მეთოდის switch განაცხადის შესაბამისი case განყოფილება GetPropValმიიღებს ფორმას:
case ePropTest1: wstring_to_p(test1, pvarPropVal); შესვენება;
მეთოდი SetPropVal:
შემთხვევა ePropTest1: if (TV_VT(varPropVal) != VTYPE_PWSTR) დააბრუნებს false; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); შესვენება;
მეორე თვისების განსახორციელებლად, ჩვენ განვსაზღვრავთ კლასის ველს CaddInNative
uint8_t ბოლო_ტიპი;
რომელშიც შევინახავთ ბოლო გადაცემული მნიშვნელობის ტიპს. ამისათვის დაამატეთ ბრძანება CaddInNative::SetPropVal მეთოდს:
ბოლო_ტიპი = TV_VT(varPropVal);
ახლა, როდესაც ვითხოვთ მეორე ქონების მნიშვნელობის წაკითხვას, ჩვენ დავაბრუნებთ მნიშვნელობას ბოლო_ტიპი, რასაც განსაზღვრული დავალება მოითხოვს.
მოდით შევამოწმოთ განხორციელებული ცვლილებების ფუნქციონირება.
ამისათვის წარმოგიდგენთ გარეგნობა 1C კონფიგურაციები ფორმაში:
ცვლადი DemoComp; Procedure When System Starts() Connect External Component("...", "DemoVK", External Component Type.Native); DemoComp = New ("AddIn.DemoVK.SomeName"); DemoComp.TypeCheck = 1; ანგარიში (სტრიქონი (DemoComp.TypeCheck)); DemoComp.Test = "ვასია"; ანგარიში (სტრიქონი (DemoComp.Test)); DemoComp.Test = "პეტია"; ანგარიში (სტრიქონი (DemoComp.Test)); ანგარიში (სტრიქონი (DemoComp.TypeCheck)); დასრულების პროცედურა
გაშვების შედეგად, ჩვენ მივიღებთ შეტყობინებების თანმიმდევრობას:
3
ვასია
პეტრე
22

მეორე და მესამე შეტყობინებები არის წინა საფეხურზე მითითებული ქონების წაკითხვის შედეგი. პირველი და მეორე შეტყობინებები შეიცავს ქონების ბოლო ნაკრების ტიპის კოდს. 3 შეესაბამება მთელ მნიშვნელობას, 22 - სტრიქონის მნიშვნელობას. ფაილში დგინდება ტიპებისა და მათი კოდების შესაბამისობა ტიპები.თ, რომელიც მდებარეობს ITS დისკზე.

მეთოდების ჩამონათვალის გაფართოება

ამოცანა:
  1. გააფართოვეთ გარე კომპონენტის ფუნქციონირება შემდეგი ფუნქციებით:
  2. შეისწავლეთ გარე კომპონენტების მეთოდების დანერგვის გზები
  3. დაამატეთ ფუნქციის მეთოდი ფუნქცია 1, რომელიც პარამეტრად იღებს ორ სტრიქონს („Parameter1“ და „Parameter2“). შედეგი არის სტრიქონი, როგორიცაა: „შემოწმება. პარამეტრი 1, პარამეტრი 2"
  4. დარწმუნდით, რომ თქვენს მიერ განხორციელებული ცვლილებები მუშაობს.

შექმნილი კომპონენტის მეთოდების დასადგენად, დეველოპერმა უნდა განახორციელოს შემდეგი მეთოდები AddInNative ბიბლიოთეკის კოდში:
GetNMethods, FindMethod, GetMethodName
შექმნილია მეთოდების შესაბამისი რაოდენობის მოსაპოვებლად, მეთოდის ნომრისა და დასახელების მოსაძებნად. თვისებების შესაბამისი მეთოდების მსგავსი
GetNParams
აბრუნებს მეთოდის პარამეტრების რაოდენობას მითითებული მიმდევრობის ნომრით; თუ ამ რიცხვის მქონე მეთოდი არ არის ან არ აქვს პარამეტრები, აბრუნებს 0-ს
GetParamDefValue
აბრუნებს მითითებული მეთოდის მითითებული პარამეტრის ნაგულისხმევ მნიშვნელობას
HasRetVal
აბრუნებს დროშას იმის შესახებ, აქვს თუ არა მეთოდს მითითებული რიგითი დაბრუნების მნიშვნელობის დაბრუნების მნიშვნელობა: true დაბრუნების მნიშვნელობის მქონე მეთოდებისთვის და ყალბიწინააღმდეგ შემთხვევაში
CallAsProc
ყალბი, ჩნდება გაშვების შეცდომა და 1C: Enterprise მოდულის შესრულება წყდება. პარამეტრების მასივის მეხსიერება გამოყოფილი და გამოთავისუფლებულია 1C: Enterprise-ის მიერ.
CallAsFunc
ახორციელებს მეთოდს მითითებული მიმდევრობის ნომრით. თუ მეთოდი დაბრუნდება ყალბი, ჩნდება გაშვების შეცდომა და 1C: Enterprise მოდულის შესრულება წყდება. პარამეტრების მასივის მეხსიერება გამოყოფილია 1C: Enterprise-ის მიერ. თუ დაბრუნებული მნიშვნელობა არის სტრიქონი ან ორობითი მონაცემთა ტიპი, კომპონენტი გამოყოფს მეხსიერებას ფუნქციასთან ერთად AllocMemoryმეხსიერების მენეჯერი, იქ წერს მონაცემებს და ინახავს ამ მისამართს სტრუქტურის შესაბამის ველში. 1C: საწარმო გაათავისუფლებს ამ მეხსიერებას დარეკვით თავისუფალი მეხსიერება.
მეთოდების სრული აღწერა, მათ შორის პარამეტრების ჩამონათვალი, დეტალურად არის აღწერილი ITS დისკზე მოწოდებულ დოკუმენტაციაში.
განვიხილოთ ზემოთ აღწერილი მეთოდების განხორციელება.
კომპონენტის კოდში ორი მასივია განსაზღვრული:
static wchar_t *g_MethodNames = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); static wchar_t *g_MethodNamesRu = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
და ჩამოთვლა:
enum მეთოდები (eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // ყოველთვის ბოლო );
ისინი გამოიყენება ფუნქციებში GetNMethods, FindMethodდა GetMethodNameთვისებების აღწერის ანალოგიით.
მეთოდები GetNParams, GetParamDefValue, HasRetValჩამრთველის განხორციელება, გავლილი პარამეტრებისა და აპლიკაციის ლოგიკის მიხედვით, დააბრუნებს საჭირო მნიშვნელობას. მეთოდი HasRetValმის კოდში მას აქვს მხოლოდ მეთოდების სია, რომლებსაც შეუძლიათ შედეგის დაბრუნება. მათთვის ის ბრუნდება მართალია. ფოლადის ყველა მეთოდისთვის ბრუნდება ყალბი.
მეთოდები CallAsProcდა CallAsFuncშეიცავდეს მეთოდის პირდაპირ შესრულებად კოდს.
მეთოდის დასამატებლად, რომლის გამოძახება შესაძლებელია მხოლოდ ფუნქციის სახით, თქვენ უნდა შეიტანოთ შემდეგი ცვლილებები საწყისი კოდიგარე კომპონენტები:
  1. დაამატეთ მეთოდის სახელი მასივებს g_MethodNamesდა g_MethodNamesRu(ფაილი AddInNative.cpp)
  2. დაამატეთ მეთოდის მნიშვნელოვანი იდენტიფიკატორი Methods enumeration-ში (ფაილი AddInNative.h)
  3. შეიტანეთ ცვლილებები ფუნქციის კოდში GetNParamsპროგრამის ლოგიკის შესაბამისად
  4. საჭიროების შემთხვევაში, შეიტანეთ ცვლილებები მეთოდის კოდში GetParamDefValue, თუ გსურთ გამოიყენოთ მეთოდის პარამეტრების ნაგულისხმევი მნიშვნელობები.
  5. შეიტანეთ ცვლილებები ფუნქციაში HasRetVal
  6. შეიტანეთ ცვლილებები ფუნქციების ლოგიკაში CallAsProcან CallAsFuncმეთოდის უშუალოდ შესრულებადი კოდის იქ განთავსება
წარმოვადგინოთ მასივები g_MethodNamesდა g_MethodNamesRu, ასევე ჩამოთვლა მეთოდებიფორმამდე:
static wchar_t *g_MethodNames = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test"); static wchar_t *g_MethodNamesRu = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test");

Enum Methods (eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // ყოველთვის ბოლო );
მოდით შევცვალოთ ფუნქცია GetNPropsასე რომ დააბრუნებს "ტესტი" მეთოდის პარამეტრების რაოდენობას:
long CAddInNative::GetNParams(const long lMethodNum) ( switch(lMethodNum) ( case eMethShowInStatusLine: return 1; case eMethLoadPicture: return 1; case eMethTest: return 2; default: return 0; ) return 0; )
მოდით შევიტანოთ ცვლილებები ფუნქციაში:
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) (TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum e eMethStartTimer : case eMethStopTimer: case eMethTest : / / არ არის პარამეტრის მნიშვნელობები ნაგულისხმევი შესვენებით: დაბრუნება false;
დამატებული ხაზის წყალობით
საქმე eMethTest:
თუ ერთი ან მეტი არგუმენტი აკლია, შესაბამის პარამეტრებს ექნება ცარიელი მნიშვნელობა ( VTYPE_EMPTY). თუ პარამეტრის ნაგულისხმევი მნიშვნელობა გჭირდებათ, ის უნდა დააყენოთ განყოფილებაში eMethTestფუნქციის შეცვლის განცხადება CAddInNative::GetParamDefValue.
ვინაიდან ტესტის მეთოდს შეუძლია დააბრუნოს მნიშვნელობა, თქვენ უნდა შეიტანოთ ცვლილებები ფუნქციის კოდში HasRetVal:
bool CAddInNative::HasRetVal(const long lMethodNum) ( switch(lMethodNum) ( case eMethLoadPicture: case eMethTest: return true; ნაგულისხმევი: return false; ) return false; )
და დაამატეთ მეთოდის შესრულებადი კოდი ფუნქციას CallAsFunc:
bool CAddInNative::CallAsFunc(const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) ( ... std::wstring s1, s2; switch(lMethodNum) (შემთხვევა eMethT case: ...eMethLoad;P; if (! lSizeArray || !paParams) return false ; ;
მოდით შევადგინოთ კომპონენტი და მივიყვანოთ კონფიგურაციის კოდი ფორმაში:
ცვლადი DemoComp; Procedure When System Starts() Connect External Component("...", "DemoVK", External Component Type.Native); DemoComp = New ("AddIn.DemoVK.SomeName"); lane = DemoComp.Test ("გამარჯობა", "მსოფლიო!"); ანგარიში(თითო); დასრულების პროცედურა
კონფიგურაციის გაშვების შემდეგ ჩვენ მივიღებთ შეტყობინებას: „გამარჯობა, მსოფლიო!“, რაც მიუთითებს იმაზე, რომ მეთოდი წარმატებით მუშაობდა.

ტაიმერი

ამოცანა:
  1. შეისწავლეთ ტაიმერის განხორციელება დემო VK-ში
  2. შეცვალეთ „StartTimer“ მეთოდი პარამეტრებში ტაიმერის პასუხის ინტერვალის (მილიწამებში) გადაცემის შესაძლებლობის დამატებით.
  3. დარწმუნდით, რომ თქვენს მიერ განხორციელებული ცვლილებები მუშაობს.

WinAPI-ში შეგიძლიათ გამოიყენოთ შეტყობინება დროზე მუშაობისთვის WM_TIMER. Ეს მესიჯიგადაეგზავნება თქვენს პროგრამას დროის ინტერვალით, რომელიც თქვენ დააყენეთ ტაიმერის შექმნისას.
ტაიმერის შესაქმნელად გამოიყენეთ ფუნქცია SetTimer:
UINT SetTimer(HWND hWnd, // ფანჯრის აღმწერი UINT nIDevent, // ტაიმერის იდენტიფიკატორი (ნომერი) UINT nElapse, // დაყოვნება TIMERPROC lpTimerFunc); // ფუნქციის მაჩვენებელი
ოპერაციული სისტემა გამოგიგზავნით შეტყობინებას WM_TIMERპროგრამაში არგუმენტში მითითებული ინტერვალით გასვლა(მილიწამებში). ბოლო პარამეტრში შეგიძლიათ მიუთითოთ ფუნქცია, რომელიც შესრულდება ტაიმერის გაშვების ყოველ ჯერზე. ამ ფუნქციის სათაური ასე უნდა გამოიყურებოდეს (სახელი შეიძლება იყოს ნებისმიერი):
void __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
მოდით განვიხილოთ ტაიმერის განხორციელება დემო VC-ში.
ვინაიდან ჩვენ განვიხილავთ Windows OS ოჯახისთვის გარე კომპონენტის შემუშავების პროცესს, ჩვენ არ განვიხილავთ ტაიმერის დანერგვას სხვა ოპერაციულ სისტემებში. GNU/Linux OS-ისთვის, კერძოდ, იმპლემენტაცია განსხვავდება ფუნქციის სინტაქსით SetTimerდა TimerProc.
შესრულებადი კოდი უწოდებს მეთოდს SetTimer, რომელსაც გადაეცემა ფუნქცია MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
შექმნილი ტაიმერის ID მოთავსებულია ცვლადში m_uiTimerრათა მოგვიანებით გამორთოთ.
ფუნქცია MyTimerProcშემდეგნაირად:
ბათილი გამოძახება MyTimerProc(HWND hwnd, // ფანჯრის სახელური ტაიმერის შეტყობინებებისთვის UINT uMsg, // WM_TIMER შეტყობინება UINT idEvent, // ტაიმერის იდენტიფიკატორი DWORD dwTime // სისტემის მიმდინარე დრო) ( if (!pAsyncEvent) *who =wchart "ComponentNative", *what = L"Timer" *wstime = new wchar_t (wstime) (wmemset(wstime, 0, TIME_LEN); ::_ultow(dwTime, wstime, 10); , რა, wstime);
ფუნქციის არსი იმაში მდგომარეობს, რომ მეთოდი ე.წ გარე ღონისძიება, რომელიც აგზავნის შეტყობინებას 1C: Enterprise სისტემაში.
მეთოდის ფუნქციონირების გაფართოება StartTimerმოდით გავაკეთოთ შემდეგი:
მეთოდის კოდის შეცვლა GetNParamsისე რომ მეთოდისთვისაა eMethStartTimerდაბრუნებული მნიშვნელობა 1:
საქმე eMethStartTimer: დაბრუნება 1;
აქ არის მეთოდის კოდი CallAsProcფორმამდე:
შემთხვევა eMethStartTimer: if (!lSizeArray || TV_VT(paParams) != VTYPE_I4 || TV_I4(paParams)<= 0) return false; pAsyncEvent = m_iConnect; #ifndef __linux__ m_uiTimer = ::SetTimer(NULL,0,TV_I4(paParams),(TIMERPROC)MyTimerProc); #else // код для GNU/Linux #endif break;
ახლა მოდით შევამოწმოთ ფუნქციონირება. ამისათვის ჩვენ ჩავწერთ კოდს კონფიგურაციის მართული აპლიკაციის მოდულში:
ცვლადი DemoComp; Procedure When System Starts() Connect External Component("...", "DemoVK", External Component Type.Native); DemoComp = New ("AddIn.DemoVK.SomeName"); DemoComp.StartTimer(2000); დასრულების პროცედურა
კონფიგურაციის დაწყების შემდეგ, პროგრამა მიიღებს შეტყობინებებს 2 წამის ინტერვალით, რაც მიუთითებს, რომ ტაიმერი მუშაობს სწორად.

ურთიერთქმედება 1C: Enterprise სისტემასთან

გარე კომპონენტსა და 1C: Enterprise სისტემას შორის ურთიერთქმედებისთვის, ფაილში აღწერილი IAddInDefBase კლასის მეთოდები AddInDefBase.h. ჩვენ ჩამოვთვლით ყველაზე ხშირად გამოყენებულ მათ:
შეცდომის შეტყობინების გენერირება
ვირტუალური bool ADDIN_API AddError (ხელმოუწერელი მოკლე wcode, const WCHAR_T* წყარო, const WCHAR_T* descr, long scode)
wcode, კოდი- შეცდომის კოდები (შეცდომის კოდების სია აღწერილობებით შეგიძლიათ იხილოთ ITS დისკზე)
წყარო- შეცდომის წყარო
აღწერ- შეცდომის აღწერა
შეტყობინების გაგზავნა 1C: Enterprise სისტემაში
ვირტუალური bool ADDIN_API ExternalEvent(WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszწყარო- შეტყობინების წყარო
wszმესიჯი- შეტყობინების ტექსტი
wszData- გადაცემული მონაცემები
შეტყობინებების აღკვეთა ხორციელდება გარე მოვლენის დამუშავების პროცედურით
გარე კომპონენტის რეგისტრაცია 1C: Enterprise სისტემაში
ვირტუალური bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszProfileName- კომპონენტის სახელი.
ეს მეთოდები საკმარისია VK-სა და 1C-ს შორის სრული ურთიერთქმედებისთვის. 1C: Enterprise სისტემიდან გარე კომპონენტის მიერ მონაცემების მისაღებად და პირიქით, გარე კომპონენტი აგზავნის სპეციალურ შეტყობინებას, რომელიც, თავის მხრივ, წყვეტს 1C სისტემას და, საჭიროების შემთხვევაში, იძახებს გარე კომპონენტის მეთოდებს მონაცემების უკან გადასაცემად. .

tVariant მონაცემთა ტიპი

გარე კომპონენტსა და 1C: Enterprise სისტემას შორის მონაცემთა გაცვლისას გამოიყენება tVariant მონაცემთა ტიპი. ის აღწერილია Types.h ფაილში, რომელიც შეგიძლიათ იხილოთ ITS დისკზე:
struct _tVariant ( _ANONYMOUS_UNION (int8_t i8Val; int16_t shortVal; int32_t lVal; int intVal; ხელმოუწერელი int uintVal; int64_t llVal; uint8_t ui8Val; uint2_Val; uint2_Val; t32_t errCode; struct tmVal* pInterfaceVal __VARIANT_NAME_2/*iface*/ სიმბოლო ) __VARIANT_NAME_1 განზომილებიანი მასივი pvarVal TYPEVAR vt);
ტიპი tVariantარის სტრუქტურა, რომელიც მოიცავს:
  • ნარევი (კავშირი), რომელიც განკუთვნილია უშუალოდ მონაცემთა შესანახად
  • მონაცემთა ტიპის იდენტიფიკატორი
ზოგადად, ტიპის ცვლადებთან მუშაობა tVariantხდება შემდეგი ალგორითმის მიხედვით:
  1. ამჟამად ცვლადში შენახული მონაცემების ტიპის განსაზღვრა
  2. შედით შესაბამის ნარევის ველზე, რათა უშუალოდ მიიღოთ მონაცემები
ტიპის გამოყენებით tVariantმნიშვნელოვნად ამარტივებს 1C: Enterprise სისტემისა და გარე კომპონენტების ურთიერთქმედებას

განაცხადი

"მაგალითები" დირექტორია შეიცავს სტატიის მაგალითებს
მაგალითები/1 - დემო კომპონენტის გაშვება
მაგალითები/2 - ქონების სიის გაფართოების დემონსტრირება
მაგალითები/3 - მეთოდების სიის გაფართოების დემონსტრირება
თითოეული დირექტორია შეიცავს VS 2008 პროექტს და მზა 1C კონფიგურაციას.

ეს სტატია ეძღვნება გარე კომპონენტებთან მუშაობას, კერძოდ, მათ დაკავშირებას. ამ დროისთვის, 1C Enterprise-ის შესაძლებლობების გასაფართოებლად, გამოიყენება გარე კომპონენტების ორი ტექნოლოგია:

  • 1 Native API-ის გამოყენება
  • 2 COM ტექნოლოგიის გამოყენებით
ამ სტატიაში გადავწყვიტე გამოვყო Native API კომპონენტებთან მუშაობა.
მაშ ასე, დავიწყოთ, მარტივიდან რთულამდე:
ამონარიდი ITS-დან

1. ვთქვათ, ჩვენი VK მდებარეობს დისკზე კონკრეტულ დირექტორიაში:

შეიძლება გამოყენებულ იქნას "სქელი კლიენტი (რეგულარული აპლიკაცია)";

ეს არის Native კომპონენტთან მუშაობის უმარტივესი მაგალითი. გთხოვთ გაითვალისწინოთ, რომ ამ ტიპის კომპონენტი არ საჭიროებს სისტემაში რეგისტრაციას, რაც მნიშვნელოვნად ამარტივებს ადმინისტრირებას.

2. ზემოთ განხილული მაგალითი სულაც არ არის რეალისტური. ყველაზე ხშირად, კომპონენტი მოთავსებულია განლაგებაში. განლაგება უნდა შეიცავდეს zip არქივს კომპონენტის ფაილებით და MANIFEST.xml ფაილით
მანიფესტის ფაილის მაგალითი:

3. თხელ და ვებ კლიენტში მუშაობისას აუცილებლად გამოიყენეთ მეთოდი.
ციტატა ITS-დან:

ახსნა:
%APPDATA%\1C\1Cv82\ExtCompT- დირექტორია სქელი და თხელი კლიენტებისთვის კომპონენტების დაყენებისთვის.
%APPDATA%\Roaming\Mozilla\Extensions- დირექტორია (ჩემს შემთხვევაში) გაფართოებები Mozilla FF/-ისთვის
მეთოდის გამოყენებისას SetExternalComponent()გამოყენებული კლიენტიდან გამომდინარე, გაფართოებები გაიხსნება შესაბამის დირექტორიაში.

გარე კომპონენტის დაყენების პროცედურის მაგალითი:

InstallExternalComponent- მეთოდი უნდა გამოიძახოთ მხოლოდ კომპონენტის საწყისი ინსტალაციის დროს და იმ შემთხვევაში, როდესაც აუცილებელია კომპონენტის დაინსტალირებული ვერსიის განახლება.

გამხდარი და სქელი კლიენტების შემთხვევაში:
საკმარისია ხელახლა შეასრულოთ გარე კომპონენტის ინსტალაციის ოპერაცია მეთოდის გამოყენებით InstallExternalComponent().

ვებ კლიენტის შემთხვევაში კომპონენტის განახლება:

  • საჭიროა მოდულის ამოღება ვებ ბრაუზერის დანამატებთან მუშაობის მექანიზმით (Mozilla FF)
  • გამოიყენეთ მეთოდი InstallExternalComponent
VK-ის დასაკავშირებლად შეგიძლიათ გამოიყენოთ შემდეგი პროცედურა:

თუ კომპონენტი არ არის დაინსტალირებული, გამონაკლისი იქნება დაშვებული.

2. არის შემთხვევები, როდესაც საჭიროა კომპონენტის დაყენება დროებითი მეხსიერებიდან (ფაილი მიიღება მესამე მხარის წყაროდან, გარე დამუშავება), ამ შემთხვევაში პირველი პარამეტრები მეთოდებში Attach External Component and Install External Component არის: არქივის მისამართი დროებით საცავში. ქვემოთ მოცემულია შესაძლო მაგალითი იმისა, თუ როგორ მუშაობს იგი:

&OnClient VariableAddressArchiveComponent; &OnClient ცვლადი კომპონენტი; &OnClient პროცედურა OnOpen(Failure) // მისამართი, შეიცავს სტრიქონს (ნავიგაციის ბმულს zip არქივის ბინარულ მონაცემებზე // დროებით საცავში) ComponentArchiveAddress = GetArchiveAddressInTemporaryStorage(); EndProcedure // WhenOpen() &OnServer // მეთოდები ConnectExternalComponent, SetExternalComponent შეიძლება მიიღოს როგორც //, როგორც პირველი პარამეტრი, სტრიქონი ფორმატში "navigation link" // (URL გარე კომპონენტის, რომელიც შეფუთულია ZIP არქივში, მსგავსი ფორმატით // GetNavigationLink). ფუნქცია GetArchiveAddressInTemporaryStorage()ProcessingObject = FormAttributesValue("ProcessingObject"); არქივის ბმული = PlaceInTemporaryStorage(ProcessingObject.GetLayout("MIKO_phone_IP"), New UniqueIdentifier); ReturnLinkToArchive; EndFunction // GetArchiveAddressInTemporaryStorage() &OnClient // პროცედურა უნდა გამოიძახოთ მხოლოდ ერთხელ, თუ კომპონენტი ჯერ არ არის დაინსტალირებული // ან საჭიროებს განახლებას Procedure InstallComponent(Command) Attempt to InstallExternalComponent(ArchiveComponentAddress); გამონაკლისის ანგარიში ("გარე კომპონენტის დაყენება ვერ მოხერხდა."); ბოლო მცდელობა; პროცედურის დასასრული // InstallComponent() &OnClient // კომპონენტის ინიციალიზაციის მთავარი პროცედურა Procedure Initialize(Command) External Component-ის დაკავშირების მცდელობა (ComponentArchiveAddress,"Comp" ,ExternalComponentType.Native); კომპონენტი = ახალი ("AddIn.Comp.MIKO_phone_IP"); გამონაკლისის ანგარიში ("ინიციალიზაციის გამონაკლისი. კომპონენტი შესაძლოა ჯერ არ არის დაინსტალირებული."); ბოლო მცდელობა; დასრულების პროცედურა

სტატიის სათაური შეიცავს ფრაზას "მუნჯებისთვის". ჩაიდანში, პირველ რიგში, საკუთარ თავს ვგულისხმობდი. მთელი ჩემი ცოდნა C++-ში დარჩა უნივერსიტეტის 3-4 წლის დონეზე, როცა 1C-ის უკუღმართ გზას დავადექი. და ყველაფერი კარგად იქნებოდა, მაგრამ ახლახან გაჩნდა ამოცანა, რომელიც მოითხოვდა გარე კომპონენტის დაწერას. მე მომიწია ჩემი მოგონებების გახსენება და C++ ცოდნის ამოღება. გამოდის, რომ ყველაფერი არც ისე საშინელია. მინდა შემოგთავაზოთ გარე კომპონენტების წერის მოკლე შესავალი.

შაბლონის კომპონენტები ITS-ზე

ITS დისკი შეიცავს სრულ დოკუმენტაციას გარე კომპონენტების მექანიზმის შესახებ, რომელსაც ავსებს მაგალითი პროექტი და შაბლონი საკუთარი განვითარებისთვის. მასალას ეწოდება "გარე კომპონენტის ტექნოლოგია". დოკუმენტაცია შესანიშნავია, მაგრამ თქვენ ჯერ კიდევ გჭირდებათ მისი გაგება და დრო, როგორც ყოველთვის, მოკლეა. სინამდვილეში, არის მხოლოდ რამდენიმე საკვანძო პუნქტი, რომლებზეც ყურადღების მიქცევა ღირს, დანარჩენი კი გაფუჭება და ამაოებაა :)

საჭირო მასალები

გარე კომპონენტის შესაქმნელად დაგვჭირდება:

  1. მასალა "გარე კომპონენტების შექმნის ტექნოლოგია", რომელიც მდებარეობს ITS-ზე
  2. გარე კომპონენტის ცარიელი შაბლონი, რომელიც მოყვება მასალას
  3. MS Visual Studio. Express ვერსია უფასოა და საკმარისზე მეტია ჩვენი საჭიროებისთვის.
  4. C++ სინტაქსის საბაზისო ცოდნა, კერძოდ:
  • ცვლადის დეკლარაციის ციკლიდან ან მდგომარეობიდან გარჩევის უნარი
  • იმის გაგება, რომ სტრიქონები მათი სუფთა სახით არ არსებობს C++-ში, არის მასივები, რისთვისაც აშკარად გჭირდებათ მეხსიერებით შეწუხება.
  • რა თქმა უნდა, საჭიროა დავალების განხორციელების უნარი მითითებულ ენაზე. მინიმუმ, C++-დან მესამე მხარის ბიბლიოთეკის გამოძახების შესაძლებლობა, რომელიც ყველაფერს თავად გააკეთებს.

დავიწყოთ თხრა

Native API-ს დოკუმენტაცია საკმაოდ დეტალურია. რომ შევაჯამოთ, ის ამბობს შემდეგს:

  1. გარე კომპონენტი საშუალებას გაძლევთ გააფართოვოთ ჩაშენებული ენა ახალი ობიექტით (ან რამდენიმე). იმათ. ჩვენ შევქმნით კლასს, რომელიც შეგვიძლია შევქმნათ "ახალი" ოპერატორის გამოყენებით და მოვუწოდებთ ამ ობიექტის მეთოდებს ჩაშენებული ენიდან.
  2. იმისათვის, რომ ჩვენმა ობიექტმა იმუშაოს, პლატფორმა „დაუკავშირდება“ მას გარკვეული პროტოკოლის გამოყენებით, რომელიც ჩვენ ვალდებულნი ვართ მოგაწოდოთ.
  3. თავად კომპონენტის კოდი პირობითად შედგება ორი ნაწილისგან: პირველი არის თავად კომპონენტის რეგისტრაცია სისტემაში, მეორე არის ახალი კლასის მოქმედება და მისი ურთიერთქმედება პლატფორმასთან.

ჩვენ არ შევეხებით განხორციელების სპეციფიკას, გვეწურება ვადები და არ გვაქვს საკმარისი კომპეტენცია. ჩვენ სწრაფად უნდა გავიგოთ, სად უნდა შევიტანოთ ჩვენი ხაზები, რომ კომპონენტმა იმუშაოს. ამისათვის აიღეთ კომპონენტის შაბლონი ITS-ით და გახსენით Visual Studio-ში. შაბლონი განთავსებულია შეუფუთავი არქივის შაბლონის საქაღალდეში. ვნახოთ რა გვაქვს აქ.

ჩვენ გვაინტერესებს AddInNative.cpp ფაილი. ყველა გაცნობიერება მასში დევს. ის შეიცავს შაბლონებს ყველა საჭირო მეთოდისთვის, უბრალოდ საჭიროა მათი ოდნავ მორგება. თუმცა, აღმოჩნდა, რომ უფრო ადვილი იყო არა ცარიელი შაბლონის საფუძვლად გამოყენება, არამედ სამუშაო მაგალითთან გამკლავება. მას აქვს რამდენიმე სასარგებლო ზარი და სასტვენი, რომლებიც არ შედის ცარიელ შაბლონში. როცა გაგება მოვა, დაგჭირდებათ ცარიელი შაბლონი აიღოთ და დახვეწოთ ამ საკითხის ცოდნით. სამუშაო კომპონენტის მაგალითი მდებარეობს example\NativeAPI საქაღალდეში, ხოლო ცარიელი შაბლონი მდებარეობს შაბლონის საქაღალდეში.

გავხსნათ პროექტი მაგალითის საქაღალდიდან და მასში - ფაილი AddInNative.cpp

ფაილის დასაწყისშივე არის მუდმივების და დამხმარე ფუნქციების დეკლარაციები. ჩვენ გვაინტერესებს შემდეგი სტრიქონები:

ჩვენი ობიექტი, როგორც „რეალური“, მხარს დაუჭერს რუსულ და ინგლისურ ენებზე დაწერილ მეთოდებს. ამ მიზნით, თვისებების და მეთოდების წერილობითი სახელები გამოცხადებულია ორ ენაზე. ლურჯი ჩარჩო განკუთვნილია ინგლისური აბანოებისთვის, წითელი ჩარჩო არის რუსული აბანოებისთვის. სურათი გვიჩვენებს, რომ მაგალითი უკვე ახორციელებს უამრავ მეთოდს და თვისებას. ჩვენი ამოცანაა მათი ამოღება და საკუთარის ჩასმა.

ხაზი, რომელშიც კლასის სახელია გამოცხადებული, მონიშნულია მწვანე ჩარჩოთი. მართალი გითხრათ, ვერ მივხვდი რას ნიშნავდა. თუ შეცვლი, არაფერი გამოდის. მას შემდეგ, რაც მათ თავდაპირველად გააკეთეს დათქმა, რომ მე ვიყავი "მატყუარა", შეიძლება მაპატიონ. :)

ამრიგად, თუ ჩვენი ობიექტი შეიცავს "RunCalculation" მეთოდს და "Destination" თვისებას, მაშინ ეს სახელი უნდა აღვწეროთ g_MethodNamesRu და g_PropNamesRu მასივებში, შესაბამისად.

ზარები 1C ენიდან

ასე რომ, ჩვენი ობიექტი შეიცავს ერთ მეთოდს და წაკითხვის-ჩაწერის თვისებას.

მოდით მივიღოთ გამოყენების შემდეგი სცენარი:

OurObject = New (“AddIn. MyComponent. DataSender”); ჩვენი ობიექტი. დანიშნულება = "somemail@server. com";
ჩვენი ობიექტი. RunCalculation (PaymentAmount, "კომუნალური მომსახურებისთვის");

არსებობს სტრიქონის თვისება და მეთოდი რიცხვითი და სტრიქონის პარამეტრით. იმისათვის, რომ ეს ყველაფერი იმუშაოს, 1C ასრულებს დაახლოებით შემდეგ საკომუნიკაციო პროტოკოლს კომპონენტთან:

პლატფორმა უწოდებს წინასწარ განსაზღვრულ ფუნქციებს ჩვენს ობიექტზე, ის პასუხობს მას და ასრულებს მის ბრძანებებს. მსგავსი სიტუაციაა მეთოდებთან დაკავშირებით, მხოლოდ იქ, მეთოდის ნომრის გარდა, მოთხოვნილი იქნება პარამეტრების რაოდენობა, დაბრუნებული მნიშვნელობის არსებობა და არჩევითი პარამეტრების არსებობა.

მოდით დავუბრუნდეთ ჩვენს კოდს. „ჯადოსნური რიცხვების“ თავიდან აცილების მიზნით, CAddInNative კლასში გამოცხადებულია ორი ჩამოთვლა, რომელიც პასუხისმგებელია მეთოდებისა და თვისებების რაოდენობის განსაზღვრაზე. მოდით გავხსნათ ფაილი CAddInNative.h და ვნახოთ ისინი თავიდანვე:

ცარიელი შაბლონი არ შეიცავს ამ ჩამოთვლას და ასევე არ არსებობს რუსულ ენაზე ზარების არარუსულიდან გამოყოფის მაგალითი. ეს მიდგომა არჩევითია. მნიშვნელოვანია დაიცვას ინტერფეისი და იქნება თუ არა გადარიცხვები, თქვენი გადასაწყვეტია.

უნიკოდის სტრიქონები

ბევრმა ალბათ იცის, რომ პლატფორმა მუშაობს ორბაიტიან სიმბოლოებზე Unicode ფორმატში. შაბლონი ამ მიზნით აცხადებს სპეციალურ ტიპს WCHAR_T. ეს ტიპი არის cross-platform wrapper და უზრუნველყოფს იგივე სიმბოლოების ზომას Windows-სა და Linux-ზე. სტანდარტული wchar_t ტიპი შეიძლება განსხვავდებოდეს ზომით სხვადასხვა სისტემაში. გთხოვთ, ასევე გაითვალისწინოთ, რომ ყველა სტრიქონი გამოცხადებულია ასო L პრეფიქსით. ეს ნიშნავს, რომ ასეთი სტრიქონი არის wchar_t ტიპის.

არსებობს მარტივი წესი: შიგადაშიგ, სიმებიანი კომპონენტები მუშავდება როგორც wchar_t (Linux-ზე შეიძლება იყოს 4 ბაიტი, Windows-ზე - 2), მაგრამ როგორც კი სტრიქონს გადავიტანთ 1C-ზე ან მივიღებთ იქიდან, გვჭირდება WCHAR_T (მკაცრად 2 ბაიტი ყველა სისტემაზე).

ერთი ტიპის სტრიქონის მეორეზე გადასაყვანად, შაბლონი უზრუნველყოფს დამხმარე ფუნქციებს:

პირველი ქმნის WCHAR_T-ს სტანდარტული wchar_t-დან:

uint32_t convToShortWchar(WCHAR_T** Dest, const wchar_t* Source, uint32_t len ​​= 0);

მეორე პირიქითაა. ფორმები wchar_t WCHAR_T-დან.

uint32_t convFromShortWchar (wchar_t** Dest, const WCHAR_T* წყარო, uint32_t len ​​= 0);

პლატფორმასთან ურთიერთობისას ყოველთვის გამოიყენება მხოლოდ WCHAR_T.

ვარიანტის ტიპი

კიდევ ერთი საინტერესო რამ არის ზოგადი Variant მონაცემთა ტიპი. ის გვაძლევს საშუალებას ვიმოქმედოთ 1C ენასთან, რომელიც, როგორც მოგეხსენებათ, არ არის აკრეფილი და მასში არსებული თითოეული ცვლადი შეიძლება შეიცავდეს ყველაფერს. ეს ტიპი გამოიყენება მნიშვნელობების გაცვლისას. RunCalculation მეთოდს გადავცემთ ორ პარამეტრს - რიცხვს და სტრიქონს. კომპონენტი მიიღებს ორ Variant მნიშვნელობას. ჩვენი პასუხისმგებლობაა მათი რეალური ტიპის შემოწმება. არავინ შეგიშლით ხელს კომპონენტზე არა რიცხვის, არამედ, ვთქვათ, მნიშვნელობების ცხრილის გადაცემაში.

თუმცა, როგორც ჩანს, ვცდები. მეჩვენება, რომ მაინც შეუძლებელი იქნება ღირებულებების ცხრილის NativeAPI-ზე გადატანა, რადგან... ის არ არის ნებადართული ტიპების ჩამონათვალში, მაგრამ, მიუხედავად ამისა, შეგიძლიათ გადასცეთ თარიღი String-ის ნაცვლად. ეს ასევე არ არის კარგი. ჩვენ უნდა შევამოწმოთ ცვლადის რეალური ტიპი, რომელიც მოვიდა 1C-დან.

ვარიანტის ტიპი მარტივია. ეს არის სტრუქტურა, რომლის თვისებები არის სხვადასხვა ტიპის ღირებულებები. არის ისეთი თვისებები, როგორიცაა DATE, wchar_t, int და სხვა. Variant-ის ძირითადი ნაწილი არის "vt" თვისება, რომელიც ინახავს ცვლადის რეალურ ტიპს და საიდანაც შეგიძლიათ ზუსტად გაიგოთ, თუ როგორ უნდა განიმარტოთ ეს ვარიანტი. გარდა ამისა, გამოცხადდა მრავალი დამხმარე მაკრო Variant ტიპის მუშაობის გასამარტივებლად.

გადადით აზრამდე

როგორც ჩანს, ეს ყველაფერი შესავალშია. მე ვთავაზობ გარე კომპონენტის განხორციელების მაგალითის განხილვას. TK იქნება კომპონენტის მაგალითი ITS დისკიდან. ეს მაგალითი აღწერს შემდეგ მახასიათებლებს:

  • ძირითადი ფანჯრის სტატუსის ზოლში ტექსტის ჩვენება;
  • გარე ტაიმერის ღონისძიების გაგზავნა;
  • ბინარული მონაცემების გადატანა 1C:Enterprise-ზე;
  • თვისებების განხორციელება;
  • პროცედურების განხორციელება;
  • ფუნქციების განხორციელება;

კომპონენტს აქვს შემდეგი API:

  • Თვისებები:
    • ჩართულია/ჩართულია;
    • IsTimer/IsTimerPresent;
    • მეთოდები:
      • ჩართვა;
      • გამორთვა/გამორთვა;
      • ShowInStatusLine;
      • EnableTimer/StartTimer;
      • გამორთეთ ტაიმერი/StopTimer;
      • LoadPicture/LoadPicture;

გარე მოვლენა ხდება ტაიმერის მიხედვით, რომლის გამოწერა შესაძლებელია 1C კოდიდან.

იმ ცოდნით ხელმძღვანელობით, რაც გვაქვს, თავიდანვე შევხედოთ კომპონენტს.

სარეგისტრაციო კომპონენტები

ჩვენი ობიექტი განხორციელებულია როგორც ცალკე C++ კლასი, ამ შემთხვევაში CAddInNative. იმისათვის, რომ 1C ნახოს ჩვენი კლასი, dll ბიბლიოთეკამ უნდა გაიტანოს 3 ფუნქცია:

  • GetClassObject
  • DestroyObject
  • GetClassNames

ეს ექსპორტები შეიძლება ნახოთ AddInNative.def ფაილში VisualStudio პროექტის ხეში. მოდით შევხედოთ ამ ფუნქციების კოდს:

უმარტივესი - GetClassNames ფუნქცია - ეუბნება 1C პლატფორმას რა კლასებია ჩვენს კომპონენტში. დაე, C++ გურუებმა შემისწორონ, მეჩვენება, რომ აქ პლატფორმამ უნდა უპასუხოს C++ კლასების სახელებით, რათა შეძლოს მათი იმპორტი. ეს არის ზუსტად ის, რისთვისაც გამოიყენება g_kClassNames მასივი, რომელსაც აქვს მწვანე „ჩარჩო“. მე კონკრეტულად არ შევამოწმე, მაგრამ თუ თქვენ უბრალოდ გჭირდებათ კომპონენტის მუშაობა, მაშინ ყველაფერი ისე უნდა დატოვოთ, როგორც მაგალითშია. ის უკვე მუშაობს, ამ დროისთვის არ არის საჭირო მისი დალაგება.

ასე რომ, GetClassNames უბრუნებს პლატფორმას კლასის სახელების მასივს, რომელიც ახორციელებს გარე კომპონენტის სასარგებლო ობიექტებს. ჩვენს მაგალითში, კომპონენტი დააბრუნებს პლატფორმას ერთი ელემენტის მასივს კლასის სახელით CAddInNative.

გთხოვთ, გაითვალისწინოთ, რომ პლატფორმა მიიღებს WCHAR_T ტიპის მნიშვნელობას, ხოლო კლასის სახელი g_kClassNames მასივში არის wchar_t ტიპის. აქედან გამომდინარე, ჩამოსხმა ხორციელდება ზემოთ განხილული დამხმარე ფუნქციის გამოყენებით.

შემდეგი ფუნქცია არის GetClassObject. დარეკა, როცა საწარმოს კოდში ჩავწერეთ „ახალი“. პლატფორმა მოითხოვს, რომ შევქმნათ კლასის ახალი ეგზემპლარი და დავაბრუნოთ მაჩვენებელი ახალ ობიექტს.

კიდევ ერთხელ, გაითვალისწინეთ, რომ პირველი პარამეტრი, რომელსაც პლატფორმა გვეუბნება, არის ის, თუ რომელი კლასი შევქმნათ (GetClassNames მეთოდით მინიჭებული კლასისგან). ვინაიდან ჩვენ გვაქვს მხოლოდ ერთი კლასი, ეს სახელი აქ საერთოდ არ არის შემოწმებული, ობიექტი უბრალოდ იქმნება new-ის საშუალებით და ბრუნდება გამომავალი პარამეტრის pInterface-ის მეშვეობით.

და ბოლო საჭირო ექსპორტის ფუნქციაა DestroyObject. სახელი თავისთავად საუბრობს. როდესაც ობიექტი აღარ არის საჭირო პლატფორმისთვის, ის უნდა წაიშალოს. ჩვენ გვეძლევა მაჩვენებელი ადრე შექმნილ ობიექტზე. ჩვენ ვათავისუფლებთ მას არასაჭირო მაჩვენებლების წაშლისა და გადატვირთვის გამოყენებით.

აღწერილი განხორციელებები საკმაოდ უნივერსალურია. თუ ჩვენი კომპონენტი ახორციელებს მხოლოდ ერთ კლასს (როგორც მაგალითში), მაშინ ეს ფუნქციები უბრალოდ უნდა დაკოპირდეს საკუთარ თავში. ერთადერთი პირობა არის სწორი კლასის შექმნა GetClassObject ფუნქციაში, თუ თქვენი სახელია არა CAddInObject, არამედ სხვა რამ.

კომპონენტის ინიცირება/შეწყვეტა

კლასის შექმნის შემდეგ, რომელიც ახორციელებს კომპონენტს, პლატფორმა უწოდებს ამ კლასის მეთოდებს. მუშაობის დაწყებამდე პლატფორმა გვეტყვის „საკუთარი თავის“ ობიექტს, რომლითაც შეგვიძლია თავად პლატფორმის გარკვეული მეთოდები დავარქვათ. ეს ხდება Init მეთოდით. მაგალითში პლატფორმის ობიექტი ინახება m_iConnect ცვლადში.

კიდევ ერთი მნიშვნელოვანი მეთოდი არის setMemManager. საშუალებას გაძლევთ გამოყოთ მეხსიერების ბლოკები, რომლებსაც თავად პლატფორმა გაათავისუფლებს. იგი ხორციელდება შემდეგნაირად:

ჩვენ უბრალოდ ვინახავთ მაჩვენებელს მეხსიერების მენეჯერისკენ, რომელსაც პლატფორმა გადმოგვცემს. შემდეგ ამ მენეჯერთან ერთად გამოვყოფთ მეხსიერების გათავისუფლებას თავად პლატფორმის მიერ.

და ისევ, როგორც ექსპორტის ფუნქციების შემთხვევაში, ინიციალიზაციის მეთოდები საკმაოდ უნივერსალურია, შეგიძლიათ უბრალოდ დააკოპიროთ ისინი საკუთარ თავს და არ ინერვიულოთ მათი „დასრულებაზე“, სანამ ეს ნამდვილად საჭირო გახდება.

ტვირთამწეობა. კომპონენტის ობიექტის მეთოდები და თვისებები

რეგისტრაცია

რა თქმა უნდა, ჩვენ შევქმენით კომპონენტი არა მისი ინიციალიზაციისთვის, არამედ სასარგებლო ფუნქციონირების მიზნით. დროა შევხედოთ როგორ განხორციელდება.

პირველ რიგში, ჩვენ უნდა დავარეგისტრიროთ ობიექტი, რომლის შექმნა და გამოძახება შესაძლებელია 1C ენიდან. ეს ობიექტი რეგისტრირებულია RegisterExtensionAs მეთოდში.

ამ მეთოდით პლატფორმას ვაცნობთ ჩვენი კლასის სახელს, რადგან ის ხილული იქნება 1C ენიდან. სწორედ ამ სახელით შევქმნით მას "ახლის" მეშვეობით. ამ შემთხვევაში, ობიექტის შექმნა შესრულდება შემდეგი კოდით:

ConnectExternalComponent(ფაილი, "MyComponent", ExternalComponentType. Native);
ობიექტის კომპონენტები = ახალი( "AddIn.MyComponent.AddInNativeExtension");

დოკუმენტაციის მიხედვით, კლასის სახელის მქონე სტრიქონის მეხსიერება გამოყოფილია მეხსიერების მენეჯერის მიერ და სახელი იწერება ამ მისამართზე - "AddInNativeExtension". აქ შეგიძლიათ უმტკივნეულოდ დაწეროთ თქვენი სახელი. გთხოვთ გაითვალისწინოთ, რომ კვლავ ხდება wchar_t-დან WCHAR_T პლატფორმაზე გადაყვანა.

გამოყენება

როგორც ზემოთ დავწერე, პლატფორმა ითხოვს კომპონენტს სხვადასხვა ენის ფუნქციებისთვის. არსებობს თუ არა მითითებული თვისება, არის თუ არა ის ჩასაწერად, აქვს თუ არა ფუნქციის პარამეტრს ნაგულისხმევი მნიშვნელობა, აქვს თუ არა დაბრუნების მნიშვნელობა და ა.შ. თუ ავიღებთ მაგალითს, რომელიც მოცემულია ადრე:

ჩვენი ობიექტი = ახალი( "AddIn.MyComponent.DataSender"); // DataSender არის სახელი RegisterExtensionAs ფუნქციიდან (განხილულია ქვემოთ).
ჩვენი ობიექტი. ადრესატი = " [ელფოსტა დაცულია]" ;
ჩვენი ობიექტი. შეასრულეთ გაანგარიშება (გადახდის თანხა, "კომუნალური მომსახურებისთვის");

შემდეგ ჩატარდება შემდეგი გამოკითხვა:

  1. არის თუ არა "დანიშნულების" საკუთრება?
  2. ჩაწერას უჭერს მხარს?
  3. არსებობს მეთოდი სახელად RunCalculation?
  4. რამდენი პარამეტრი აქვს?
  5. აქვს თუ არა მას დაბრუნების მნიშვნელობა
  6. რა არის ნაგულისხმევი პარამეტრები არასავალდებულო პარამეტრებისთვის (ასეთის არსებობის შემთხვევაში)

აქ ყველაზე სასარგებლო რამ არის მაგალითის ნახვა და დოკუმენტაციის შემოწმება. ყველა ამ კვლევის განხორციელება საკმაოდ მარტივია. მეთოდების მთელი ზოოპარკი პასუხისმგებელია ურთიერთქმედებაზე. მე არ გავივლი ყველაფერს, ისინი საკმაოდ კარგად არის დოკუმენტირებული და გარდა ამისა, მათი განხორციელება მარტივია. განიხილება მხოლოდ ყველაზე მნიშვნელოვანი მომენტები, რომლებშიც ჩვენ, როგორც მატყუარებს, დაგვჭირდება მათზე ხელის დაჭერა :). ძირითადი მიდგომა ასეთია: პირველად რომ მოიხსენიება საკუთრება ან მეთოდი, პლატფორმა მოგვთხოვს მისი სახელით მოძიებას. ჩვენ მოგვიწევს პასუხის გაცემა ამ ქონების (მეთოდის) უნიკალური ნომრით. ყველა შემდგომი კომუნიკაცია განხორციელდება მხოლოდ ნომრებით. სწორედ აქ დაგვეხმარება აღნიშნული ჩამოთვლები, რომლებიც ინახავს ამ ნომრებს.

Თვისებები

პირველი, რაც გასათვალისწინებელია არის ქონების ინფრასტრუქტურა. პლატფორმა ითხოვს ქონების არსებობას FindProp მეთოდის გამოყენებით

პლატფორმა გვაწვდის იმ ქონების სახელს, რომელსაც ვეძებთ WCHAR_T სახით. იგი გარდაიქმნება wchar_t-ად დამხმარე მეთოდის გამოყენებით და ეს ტექსტი იძებნება ჯერ ინგლისურენოვანი, შემდეგ კი რუსულენოვანი ტერმინებით. ჩვენ უნდა დავაბრუნოთ ქონების ნომერი. გაითვალისწინეთ, რომ findName დამხმარე ფუნქცია აქ არის ჩართული. მისი განხორციელება მოცემულია მაგალითში, მაგრამ კომპონენტი არ არის ცარიელ შაბლონში. მიზანშეწონილია გადაიტანოთ იგი თქვენსკენ, თუ თქვენ გეგმავთ ორენოვანი ტერმინების გამოყენებას თქვენს კომპონენტში.

შემდეგი, GetPropName მეთოდი ასრულებს საპირისპირო დავალებას, იღებს საკუთრების სახელს მისი ნომრით. სახელის სტრიქონი ასევე გამოყოფილია საწარმოს მეხსიერების მენეჯერის მეშვეობით. მეეჭვება, რომ GetPropName მეთოდი GetNProps-თან ერთად გამოიყენება, როდესაც ჩვენ გავაფართოვებთ ობიექტის თვისებებს პლიუს ნიშნით გამართულში. შემდეგ პლატფორმა მიიღებს საკუთრების მთლიან რაოდენობას და ითხოვს თითოეული მათგანის სახელს.

შემდეგი წყვილი მეთოდებია IsPropReadable/IsPropWritable. აქ ყველაფერი მარტივია, მითითებულ ქონების ნომრისთვის უნდა ვთქვათ შეიძლება თუ არა მისი წაკითხვა/ჩაწერა.

მნიშვნელობების მიღება და ჩაწერა ხდება GetPropVal/SetPropVal მეთოდების გამოყენებით. აქ ღირს უფრო დეტალურად გაცნობა. ჩვენ ვიწყებთ მუშაობას 1C: Enterprise ტიპებთან, რაც ნიშნავს, რომ Variant გამოდის სცენაზე.

კომპონენტის შაბლონი განსაზღვრავს დამხმარე მაკროების ერთობლიობას Variant-თან მუშაობის გასამარტივებლად. პირველი არის ღირებულების ტიპის შემოწმება. მაგალითად, მაკრო TV_VT საშუალებას გაძლევთ შეამოწმოთ/დააყენოთ მნიშვნელობის ტიპი. დასახელებული მუდმივები ასევე განისაზღვრება თითოეული მხარდაჭერილი ტიპისთვის. ეს მუდმივები და მათი შესაბამისობა 1C: Enterprise ტიპებთან ჩამოთვლილია დოკუმენტაციაში.

TV_BOOL მაკრო იღებს ლოგიკურ მნიშვნელობას იმ ვარიანტიდან, რომლითაც შეგიძლიათ მუშაობა. ანალოგიით, მიიღება მთელი მნიშვნელობები (TV_INT), სტრიქონები (TV_WSTR) და სხვა. ზუსტი მნიშვნელობები კოდშია, მათი ნახვა ყოველთვის შეგიძლიათ.

მნიშვნელოვანი ისაა, რომ არ არის საკმარისი მნიშვნელობის მინიჭება ვარიანტისთვის, თქვენ ასევე უნდა მივანიჭოთ რეალური ტიპი. ყურადღება მიაქციეთ GetPropVal-ს. გარდა TV_BOOL = ჭეშმარიტი მინიჭებისა, არსებობს ტიპის მინიჭება: TV_VT = VTYPE_BOOL. თუ ტიპი არ არის მინიჭებული, პლატფორმა არ იცის, რა ტიპის მნიშვნელობა დაბრუნდა მას. რა თქმა უნდა, შეგიძლიათ გააფუჭოთ და დააყენოთ არასწორი ტიპი. ამას ხშირად თან ახლავს პლატფორმის დაცემა.

მოდით შევაჯამოთ ზემოთ:

ჩვენ ვიღებთ მნიშვნელობას ვარიანტიდან:

bool someVariable = TV_BOOL(pVariant);

ჩაწერეთ ოფციონის მნიშვნელობა:

TV_VT(pVariant) = VTYPE_BOOL; // მონაცემთა სწორი ტიპი

TV_BOOL(pVariant) = someBooleanVariable; // დააყენეთ მნიშვნელობა თავად

ახლა კი - ხუჭუჭა მეთოდები!

მეთოდები ცოტა უფრო რთულია, მაგრამ ზოგადად ისინი თვისებების მსგავსია. ჯერ ერთი, არის ზუსტად იგივე ფუნქცია, რომ მოიძიოთ მეთოდი სახელით, მიიღოთ მეთოდების საერთო რაოდენობა, მიიღოთ სახელი რიცხვით. თუმცა, გარდა ზემოაღნიშნულისა, ემატება შემდეგი მახასიათებლები:

  • თუ მეთოდს შეუძლია დააბრუნოს მნიშვნელობა, მაშინ ის შეიძლება გამოყენებულ იქნას "გამოთვლაში" და ჩაიწეროს დავალების ოპერაციის მარჯვნივ 1C ენაზე. თუ არა, მაშინ ეს პროცედურაა და მსგავსი რამ გამონაკლისს გამოიწვევს "პროცედურის გამოყენება, როგორც ფუნქცია".
  • მეთოდს აქვს პარამეტრები. პლატფორმამ უნდა იცოდეს მათი ნომერი. თუ ზარი განსაზღვრავს მეტ არგუმენტს, ვიდრე მითითებულია მეთოდის ხელმოწერაში, ჩნდება შეცდომა „ძალიან ბევრი პარამეტრი“.
  • თუ მეთოდს არ გადაეცემა საკმარისი არგუმენტები, მაშინ ზოგიერთი მათგანი შეიძლება იყოს არასავალდებულო, ხოლო თუ არ არის არასავალდებულო პარამეტრები, მაშინ ჩნდება შეცდომა "არასაკმარისი პარამეტრები".
  • გამოძახებისას, თუ ეს პროცედურაა, მაშინ არ შეიძლება იყოს დაბრუნებული მნიშვნელობა. თუ ეს ფუნქციაა, მაშინ არის დაბრუნებული მნიშვნელობა. ასევე საჭიროებს დამუშავებას.

არსებობს რამდენიმე მარტივი მეთოდი, რომელთა დანიშნულება აშკარაა მათი სახელებიდან და დოკუმენტაციის მიხედვით. მათ შორისაა HasRetVal, GetNParams, GetParamDefValue. მე ვთავაზობ, რომ არ განიხილონ ისინი საკმარისზე მეტია. ჩვენი ინტერესი იქნება მიმართული დატვირთვის პირდაპირი განხორციელებისკენ. ის დანერგილია CallAsProc და CallAsFunc მეთოდებში. პირველი პასუხისმგებელია გამოძახების პროცედურებზე, მეორე პასუხისმგებელია გამოძახების ფუნქციებზე. ისინი განსხვავდებიან იმით, რომ CallAsFunc-ს აქვს დამატებითი გამომავალი პარამეტრი, რომელშიც ჩვენ გადავცემთ ფუნქციის დაბრუნებულ მნიშვნელობას პლატფორმაზე.

გამოძახება ხორციელდება შემდეგნაირად: პლატფორმა გადმოგვცემს გამოძახებული მეთოდის ნომერს, ფაქტობრივი პარამეტრების მასივს და მათ რაოდენობას. ჩვენ უნდა გავაანალიზოთ მეთოდის ნომერი და მივცეთ მას გავლილი პარამეტრები. ფუნქციის შემთხვევაში, ჩვენ ასევე უნდა ჩავწეროთ რაღაც დაბრუნებულ მნიშვნელობაში.

მაგალითში მეთოდის ნომერი გაანალიზებულია გადართვის/შემთხვევაში და რიცხვიდან გამომდინარე შესრულებულია მეთოდის ლოგიკა. ჩართვა/გამორთვა მეთოდებისთვის უბრალოდ აირჩიეთ ჩამრთველი. საინტერესოა ShowInStatusLine მეთოდი. ის აჩვენებს რა გადაეცა მას 1C:Enterprise ფანჯრის სტატუსის ზოლში. ამისთვის ვიყენებთ m_iConnect პლატფორმის შეერთების ობიექტს, რომელიც „გაგვეცა“ კომპონენტის რეგისტრაციისას. მისი შესაძლებლობების სრული სია აღწერილია დოკუმენტაციაში.

საინტერესო წერტილი. აქ, მაგალითში, 1C-დან შემოსული მნიშვნელობის ტიპი არ არის შემოწმებული, მაგრამ SetStatusLine უბრალოდ იწოდება სტრიქონის ნაწილით Variant. მეეჭვება, რომ თუ თქვენ გამოიძახებთ კომპონენტის მეთოდს 1C ენიდან, იქ გადასცემთ რიცხვს ან თარიღს (სტრიქონის ნაცვლად), მაშინ არაფერი იმუშავებს... ისევ გურუებმა შეასწორონ, მაგრამ როგორც ჩანს, pwstrVal მაჩვენებელი მიუთითებს. ღმერთმა იცის საიდან თუ საწარმოდან მოვიდა ვთქვათ ნომერი და არა პატიოსანი სტრიქონი. SetStatusLine-ის დარეკვისას, პლატფორმა შეეცდება წაიკითხოს ხაზი უცნობი მისამართიდან და, დიდი ალბათობით, ავარიული იქნება. უმჯობესია ყოველთვის შეამოწმოთ მოსალოდნელი ტიპი. Არასოდეს იცი.

მაგალითში LoadImage ფუნქცია განხორციელებულია უფრო საინტერესო გზით, ის ითვალისწინებს სტრიქონების და ორობითი მონაცემების გაცვლის შესაძლებლობას პლატფორმასთან.

პირველ რიგში, აქ შემოწმდება გადაცემული პარამეტრების რაოდენობა. თუ ისინი არ არიან, მაშინ ზარი ჩაითვლება წარუმატებლად. აბრუნებს false-ს, რომელიც პლატფორმის მიერ ინტერპრეტირებულია, როგორც ზარის შეცდომა.

შემდეგი, აქ შემოწმდება გავლილი პარამეტრის ტიპი. თუ ეს არის ვიწრო სტრიქონი (VTYPE_PSTR), მაშინ გამოიყენება ვარიანტის char ნაწილი. მაგალითში წერია paParam->pstrVal, მაგრამ შეგიძლიათ გამოიყენოთ TV_STR მაკრო, იგივე იქნება, მაგრამ ოფციონთან მუშაობის ერთგვაროვნებაც შენარჩუნდება.

თუ ეს არის ფართო სტრიქონი (VTYPE_PWSTR), მაშინ კონვერტაცია კეთდება ჯერ wchar_t-ზე და შემდეგ char-ზე. ფაქტია, რომ ფაილის გზა გადადის 1C ენიდან ამ მეთოდზე, რომელიც შემდეგ გამოიყენება fopen(char*) ფუნქციაში. ეს ფუნქცია შესაყვანად საჭიროებს char* ტიპს და WCHAR_T გამოგვიგზავნება პლატფორმიდან. ამისთვის სწორი ოპერაციადა ხორციელდება სტრიქონების კონვერტაციები.

და ბოლოს, თუ ეს საერთოდ არ არის სტრიქონი, მაშინ ზარი ჩაითვლება წარუმატებლად და ცრუ ბრუნდება.

ჩვენ გამოვყოფთ მეხსიერებას ორობითი მონაცემებისთვის მეხსიერების მენეჯერის გამოყენებით. ეს ლოგიკურია, ორობითი მონაცემები გახდება სრულფასოვანი ობიექტი პლატფორმის შიგნით და მისი მართვა უნდა მოხდეს. მეხსიერება გამოყოფილია pvarRetValue ვარიანტისთვის, რომელიც არის გარე კომპონენტის ფუნქციის დაბრუნების მნიშვნელობა.

გარდა ამისა, მთელი ფაილი იკითხება გამოყოფილ ბუფერში; აუცილებლადბაიტის ზომა მითითებულია strLen ვარიანტის თვისებაში და VTYPE_BLOB ოფციის მონაცემთა ტიპი. თუ მეხსიერება წარმატებით არის განაწილებული, მაშინ ჩვენ ვუბრუნებთ true, როგორც მთელი ფუნქციის წარმატებული გამოძახების ნიშანი.

ამრიგად, როდესაც 1C ენაზე წერია:

BinaryData = კომპონენტი. ატვირთეთ სურათი("C:\pic.jpg");

გამოიძახება კომპონენტის ობიექტის CallAsFunc მეთოდი, რომელიც გაივლის გზას და დააბრუნებს ორობით მონაცემებს, როგორც ზემოთ იყო აღწერილი.

წარმატების შემთხვევაში, BinaryData ცვლადი შეიცავს სრულფასოვან 1C ენის ობიექტს. როდესაც ის დატოვებს ფარგლებს, მასში დაკავებული მთელი მეხსიერება გათავისუფლდება პლატფორმის მიერ. სწორედ ამიტომ იყო გამოყოფილი მეხსიერების მენეჯერის მეშვეობით.

დასკვნა

მოთხრობა დაიწერა ჩაიდანმა დუმბებისთვის, ამიტომ, სავარაუდოდ, იგი სავსეა ტერმინოლოგიური უზუსტობებით. თუმცა, ამ სტატიის მიზანია გარე კომპონენტების სწრაფი გაცნობა. თუ გჭირდებათ კომპონენტის სწრაფად დამზადება მოკლე დროში, ზედმეტი პრობლემების გარეშე, ხანგრძლივი დისკუსიების გარეშე, იმედი მაქვს, რომ ეს სტატია დაგეხმარებათ. თუ ჩემი რომელიმე შეცდომა გაგრძნობინებთ თავს ცუდად, როგორც C++ გურუ, გთხოვთ, შემატყობინოთ კომენტარებში და ჩვენ გამოვასწორებთ.

Გმადლობთ ყურადღებისთვის.

გარე კომპონენტების ტექნოლოგია საშუალებას გაძლევთ შექმნათ პროგრამები (გარე კომპონენტები), რომლებიც დინამიურად დაუკავშირდებიან და მჭიდროდ იმოქმედებენ 1C:Enterprise 8 სისტემასთან, აფართოებენ მის შესაძლებლობებს. ეს ტექნოლოგიასაშუალებას გაძლევთ დააკავშიროთ სხვადასხვა საცალო აღჭურვილობა 1C:Enterprise 8 სისტემასთან: შტრიხკოდების სკანერები, ეტიკეტების პრინტერები და ა.შ.

მშობლიური API

ტექნოლოგია გამოიყენება გარე კომპონენტების შესაქმნელად მშობლიური API– საკუთარი სისტემური პროგრამირების ინტერფეისი 1C:Enterprise 8. იგი მხარს უჭერს მუშაობას ვინდოუსის სისტემებიდა Linux და შესაძლებელს ხდის შექმნას გარე კომპონენტები, რომლებიც მუშაობენ ამა თუ იმ ოპერაციული სისტემის ქვეშ. Native API ტექნოლოგიის გამოყენებით შექმნილი კომპონენტები შეიძლება იყოს დაკავშირებული სქელ კლიენტში, შიგნით თხელი კლიენტი, ვებ კლიენტში, გარე კავშირში და აპლიკაციის სერვერზე.

ჩაშენებული ენის გაფართოება

გარე კომპონენტები საშუალებას გაძლევთ გააფართოვოთ ჩაშენებული ენა ახალი ობიექტებით. გარე კომპონენტების მექანიზმების სტრუქტურები მაქსიმალურად ახლოსაა 1C:Enterprise 8 სისტემის შიდა სტრუქტურებთან, რაც ზრდის საოპერაციო ეფექტურობას.

პროცედურის გამოძახება გარე კომპონენტის მიერ კონტროლირებადი მოვლენების დასამუშავებლად

გარე კომპონენტს შეუძლია გაზარდოს მოვლენები, რომლებიც დამუშავებულია წინასწარ განსაზღვრული ენის პროცედურაში გარე მოვლენების მართვა. ეს საშუალებას გაძლევთ დააკავშიროთ სკანერები და სხვა მოწყობილობები, რომლებიც საჭიროებენ მონაცემთა ასინქრონულ გაცვლას 1C:Enterprise 8 სისტემასთან.

საკუთრების გვერდის დამატება 1C:Enterprise 8 პარამეტრებში

გარე კომპონენტებს შეუძლიათ დაამატონ თავიანთი საკუთრების გვერდები 1C:Enterprise 8 სისტემის პარამეტრების დიალოგში. ამრიგად, საცალო აღჭურვილობის ჩართვა და მართვა შესაძლებელია 1C:Enterprise 8 სისტემისთვის.

კომპონენტის პარამეტრების შენახვა "1C:Enterprise 8" პარამეტრების შენახვის მექანიზმის მეშვეობით

მისი პარამეტრების შენახვისას, გარე კომპონენტს შეუძლია გამოიყენოს 1C: Enterprise 8 სისტემის მექანიზმები.

სტატუსის ზოლზე წვდომა

ექსპლუატაციის დროს, გარე კომპონენტის მდგომარეობა შეიძლება აისახოს 1C: Enterprise 8 სისტემის სტატუსის პანელში.

ოლეგ ფილიპოვი ANT-Inform, განვითარების დეპარტამენტის უფროსის მოადგილე, [ელფოსტა დაცულია]

1C:Enterprise-ის ფუნქციონირების გაფართოება
ნაწილი 1: გარე COM კომპონენტები

ყოველი 1C დეველოპერის ცხოვრებაში დგება მომენტი, როდესაც მისთვის დაკისრებული ამოცანები აღემატება 1C პლატფორმის შესაძლებლობებს. მოდით შევხედოთ გზებს "შესაძლებლის საზღვრის გადალახვისთვის"

გამოცდილმა 1C დეველოპერებმა ალბათ უკვე გამოიცნეს სტატიის სათაურის პირველი სამი სიტყვიდან, რომ საუბარი იქნება 1C:Enterprise-ის გარე კომპონენტებზე. ეს ტექნოლოგია არსებობდა 1C:Enterprise 7.7 პლატფორმის (ან უფრო ადრე) დღიდან. ისტორიულად, იგი ძირითადად აგვარებდა კომერციულ აღჭურვილობასთან ურთიერთქმედების პრობლემებს (შტრიხკოდების სკანერები, ელექტრონული სასწორები, KKM), რომლის დროსაც საჭირო ხდება 1C პლატფორმისთვის აღჭურვილობის მიერ ინიცირებული გარკვეული მოვლენების დამუშავება. ასეთი მოვლენები სხვა არაფერია, თუ არა COM/LPT პორტებზე შემოსული ბაიტების თანმიმდევრობა. რა თქმა უნდა, 1C პლატფორმის ადაპტაცია ასეთი დაბალი დონის მექანიზმებთან მუშაობისთვის არ იქნებოდა ძალიან სწორი, ამიტომ ჩვენ გამოვიმუშავეთ გარე კომპონენტების ტექნოლოგია 1C: Enterprise-ისთვის.

სტატიების ამ სერიაში ჩვენ არ ვისაუბრებთ მხოლოდ გარე კომპონენტებზე: გარე კომპონენტები საკმაოდ მძლავრი და რთული მექანიზმია, ამიტომ მათი გამოყენება ზოგიერთი პრობლემის გადასაჭრელად განიხილება როგორც "ბეღურების სროლა ქვემეხით". თუმცა, გარე კომპონენტები ყველაზე მეტად უნივერსალური საშუალებაყველა სახის პრობლემის გადასაჭრელად, რომელიც სცილდება 1C:Enterprise პლატფორმას, ამიტომ დავიწყებთ მათ. სტატიაში განხილული იქნება გარე კომპონენტების შექმნის უძველესი, ყველაზე ხშირად გამოყენებული და დროში გამოცდილი ტექნოლოგია - COM-ზე დაფუძნებული.

რა არის გარე კომპონენტები

გარე კომპონენტები, როგორც ზემოთ აღინიშნა, გამოჩნდა 1C: Enterprise-ში 7.7 ვერსიიდან. თავდაპირველად, ტრადიციის თანახმად, 1C პლატფორმის დეველოპერები "არ შეწუხდნენ" და გარე კომპონენტები იყო ობიექტი გარკვეული სავალდებულო თვისებებით და მეთოდებით. კომპონენტები დღემდე არსებობს იმავე ფორმით. ანუ 1C:Enterprise 7.7-ისთვის დაწერილი კომპონენტები (თეორიულად) ასევე იმუშავებს 1C:Enterprise 8.3-თან.

პრაქტიკაში, არსებობს მთელი რიგი დახვეწილობა: თუ გარე კომპონენტი აქტიურად ურთიერთქმედებს თავად პლატფორმასთან, მაშინ მისი ფუნქციები სპეციალიზირებული იქნება კონკრეტული ვერსიისთვის.

8.2 ვერსიიდან, 1C: Enterprise-მა შემოიტანა ახალი ტექნოლოგია გარე კომპონენტების განვითარებისთვის, ე.წ. NativeAPI. ამ ტექნოლოგიის გამოყენებით დაწერილი კომპონენტები აღარ არის COM ობიექტები. ერთის მხრივ, ეს არის პლუსი - ეს კომპონენტები არ საჭიროებს რეგისტრაციას, მეორეს მხრივ, მათი გამოყენება სადმე სხვაგან, გარდა 1C:Enterprise პლატფორმისა, შეუძლებელია. გარე კომპონენტების შემუშავება გარკვეულწილად გართულდა, ცოტათი დიდი რაოდენობითმათ უნდა მხარი დაუჭირონ სავალდებულო ინტერფეისებს. მაგრამ ამაზე მომდევნო სტატიაში ვისაუბრებთ.

გარე კომპონენტები და COM ტექნოლოგია

თავად COM ტექნოლოგიას დეტალურად არ აღვწერ, რადგან ამ თემაზე უამრავი ლიტერატურა არსებობს. ალბათ უბრალოდ უნდა ითქვას, რომ ბევრი ადამიანი „აბნევს“ რეგულარული inproc სერვერის შექმნას 1C:Enterprise-სთვის გარე კომპონენტების შექმნით, მაგრამ ეს შორს არ არის სიმართლისგან. ძალიან ხშირად შეგიძლიათ მხოლოდ ამ ფუნქციით გაუმკლავდეთ. როგორ შევქმნათ COM ობიექტი Visual Studio-ში აღწერილია მრავალ სხვადასხვა წყაროში. კერძოდ, პირმა დაწერა დეტალურად, თუ როგორ კეთდება ეს, 1C: Enterprise-დან ზარის მაგალითით.

თუ თქვენ მაინც გსურთ შექმნათ სრულფასოვანი COM გარე კომპონენტი 1C:Enterprise-ისთვის (იმ ვარიანტებიდან, თუ რატომ შეიძლება ეს იყოს საჭირო, მე შემიძლია მოვიფიქრო მხოლოდ ერთი - კომპონენტი აქტიურად უნდა ურთიერთობდეს სისტემასთან 1C პლატფორმაზე, აცნობოს მომხმარებლებს, შეცვალეთ სტატუსის ხაზი, აჩვენეთ დიალოგური ფანჯრები და ა.შ.), მაშინ პირდაპირ უნდა გამოიყენოთ გარე კომპონენტების ტექნოლოგია. ასე რომ, დავიწყოთ.

გააზიარეთ