X++ do CIL

Dynamics AX 2012 dokáže generovat Common Intermediate Language z X++. To umožňuje spouštět daleko více kódu v běhovém prostředí Common Language Runtime a přepínání mezi běhovým prostředím pro X++ a CLR může být značně zredukováno, což má oboje pozitvní vliv na výkon.

Mnoho vývojářů to celé považuje trochu za černou magii, což má občas za následek zbytečné komplikace. Proto bych se chtěl o pár poznatků podělit. Tento článek popisuje některé základní pojmy a to, kam se ukládá kód vygenerovaný z X++. Později bych chtěl napsat více o vlastním překladu z X++ do CIL.

CIL

CIL (Common Intermediate Language), dříve nazývaný MSIL (Microsoft Intermediate Language) nebo někdy zkrátka IL je nízkoúrovňový jazyk používaný .NET Frameworkem (a projektem Mono). Běhové prostředí (CLR) nepracuje přímo s vysokoúrovňovými jazyky jako C#, pracuje s CIL a kompilátory vysokoúrovňových jazyků pouze generují CIL. Běhové prostředí zpracovává CIL stejným způsobem bez ohledu to, zda byl vygenerován ze C#, Visual Basicu, Iron Pythonu nebo z X++.

Když je kus CIL kódu poprvé použit, CLR ho zoptimalizuje pro konkrétní procesor a zkompiluje do nativního kódu.

Generování CIL z X++

Některý X++ kód běží defaultně jako CIL (dávkové úlohy, webové služby) a i jiný X++ kód můžete explicitně spouštět v CIL (viz X++ Compiled to .NET CIL). Vždy jde o serverový kód – vygenerovaný CIL není dostupný na klientu. Ne každý X++ kód lze transformovat do CIL – podporovány jsou pouze typy (třídy, tabulky a výčtové typy), kód nesmí používat runbuf() a tak podobně.

K vygenerování CIL se typicky používají tlačítka Generate Incremental CIL nebo Generate Full CIL ve vývojovém prostředí.

Sestavení a moduly

Stejně jako jakýkoli jiný CIL kód je i CIL vygenerovaný z X++ uložen do sestavení (assembly). Sestavení jsou základní stavební bloky .NET aplikací, které seskupují typy, poskytují dodatečné informace (manifest), verzování a tak dále. Mohou mít podobu spustitelné aplikace (.exe) nebo knihovny tříd (.dll).

Ale na rozdíl od většiny sestavení, sestavení vygenerované z X++ kódu se skládá z velkého množství souborů. DLL soubor neobsahuje žádný kód – pouze odkazuje na jiné soubory známé jako moduly a všechny tyto soubory dohromady tvoří jednu logickou jednotku. Výhoda tohoto přístupu je v tom, že jednotlivý modul je načten pouze pokud je potřeba některý z v něm obsažených typů. Jak uvidíte, kódu vygenerovaného z X++ je skutečně hodně, takže je znát, pokud stačí načíst jeho malou část.

Dynamics.Ax.Application

Sestavení s CIL kódem vygenerovaným z X++ se nachází v adresáři bin\XppIL na AOS (například c:\Program Files\Microsoft Dynamics AX\60\Server\MyAos\bin\XppIL). Skládá se z těchto souborů:

Soubor Popis
Dynamics.Ax.Application.dll Obsahuje odkazy na moduly a informaci, kde najít jednotlivé typy.
Enums.netmodule Obsahuje výčtové typy v CIL vygenerované z výčtových typů v X++.
InterfaceTypes.netmodule Obsahuje rozhraní (např. Enumerable).
KernelTypes.netmodule Obsahuje typy definované v AOT pod System Documentation. Nicméně některé důležité typy jsou už definovány jako CLR typy v jiných sestaveních a nejsou generovány z X++.
Dynamics.Ax.Application.dll{n}.netmodule
kde {n} ∈ <0, 999>
Tyto moduly obsahují všechny ostatní X++ typy (tzn. třídy a tabulky, včetně tabulkových map a pohledů). Celková velikost je zhruba 200 MB, takže je skutečně důležité, že nemusíme vše načítat do paměti.

Dekompilace

Jedna významná výhoda (a občas nevýhoda) CIL kódu je v tom, že je relativně čitelný a může být dekompilován zpět do jazyků vyšší úrovně, což je velmi užitečné pro zkoumání existujícího kódu a pochopení, jak přesně funguje. V tomto případě můžete vidět, jak je X++ kód přeložen do CIL (nicméně většina jádra AX je napsaná v nativním kódu, takže toto se jí netýká).

K získání CIL kódu ze sestavení můžete použít IL Disassembler. K dekompilaci CIL použijte třeba Reflector (oblíbený open-source program ILSpy naneštěstí nepodporuje sestavení s více moduly).

Abyste se mohli podívat na konkrétní typ, musíte nejprve vědět, v jakém modulu se nachází. Jedna možnost je podívat se do manifestu v Dynamics.Ax.Application.dll – ten obsahuje reference jako je tato:

.class extern public Dynamics.Ax.Application.Dialog
{
    .file Dynamics.Ax.Application.dll11.netmodule
    .class 0x02000025
}

Použijte hledávání v textu k nalezení požadovaného typu; jméno modulu vidíte ve vlastnosti .file.

Nebo se  můžete držet způsobu, který k distribuci typů do modulů používá AX. Vezměte ID objektu, vydělte 10, zaokrouhlete dolů, vezměte poslední tři číslice, odstraňte úvodní nuly a toto číslo použijte v názvu .netmodule souboru. Například: tabulka AifExceptionMap má ID 100029. Po vydělení 10 a zaokrouhlení dolů dostanete 10002. Poslední tři číslice jsou 002, takže AifExceptionMap se nachází v souboru Dynamics.Ax.Application.dll2.netmodule. Toto je samozřejmě implementační detail, který se může kdykoli změnit (počet modulů je dokonce konfigurovatelný), ale určitě není špatné to vědět.

2 Comments

  1. questions about the CIL
    When we do the compile to CIL, does that then get stored in the DB?
    When we do a modelstore movement to another AOS instance, the CIL doesn’t have to get recompiled, because it comes off of the DB?

    Wondering if you can talk about the storage mechanism of the CIL.
    Possibly i am off base on this idea.

  2. You’re right, it’s stored in DB. I’ll try to write something more when I get some time; unfortunately I have no idea when it will be.

Comments are closed.