Začátečník

Pokročilý

Profesionál

Programování ve více jazycích

Visual Basic .NET a Visual C++ .NET

 

Budete potřebovat přibližně 2 hodiny

Operační systém použitý v příspěvku: Windows XP

Vývojové nástroje: Visual Studio .NET

 

 

Vážení čtenáři,

 

hlavním námětem pro dnešek je problematika „míchání“ programovacích jazyků. V následujících kapitolách se pokusíme přijít na to, jak může být pro programátora přínosná práce ve dvou (nebo i více) programovacích jazycích. Dále se budeme soustředit na praktickou demonstraci filozofie programování ve více jazycích a vytvoříme dynamicky linkovanou knihovnu (DLL) v prostředí Visual C++ a posléze využijeme možností vytvořené knihovny ve Visual Basicu. Věřím, že vás námět dnešní diskuse zaujal, a proto neztrácejme čas a ponořme se hlouběji do problematiky.

 

Obsah

Filozofie programování ve více jazycích

Kladné a záporné stránky filozofie programování ve více jazycích

VB .NET a VC++ .NET: Krok 1 – Tvorba dynamicky linkované knihovny

Tvorba nového typu projektu ve VC++ .NET

Vysvětlení základní struktury programového kódu ve VC++ .NET

Přidání programového kódu pro exportovanou funkci

Tvorba definičního souboru (.DEF)

Kompilace dynamicky linkované knihovny ve VC++ .NET

VB .NET a VC++ .NET: Krok 2 – Využití dynamicky linkované knihovny ve VB .NET

Přidání projektu VB .NET do stávajícího řešení

Deklarace exportované funkce ve standardním modulu

Testování exportované funkce

Sestavení dynamicky linkované knihovny v distribučním provedení

 

 

Filozofie programování ve více jazycích

 

Možná, že s uvedeným termínem „míchání programovacích jazyků“ (angl. Mixed Language Programming) se střetáváte poprvé, možná, že jste o něm již „něco“ slyšeli, no stále nevíte, o co ve skutečnosti jde. Pojďme se tedy podívat, jak se tato myšlenka dostala do světa, ve kterém vládnou optimalizované algoritmy a počítačové instrukce. Jak jistě víte, v počítačovém světe existuje poměrně početná množina programovacích jazyků, od těch nejstarších (ALGOL, COBOL, FORTRAN), přes C a BASIC až po nejnovější instance, jakými jsou Visual Basic .NET, Visual C# .NET nebo Visual C++ .NET. Každý programovací jazyk, který se nachází na určitém vývojovém stupni, byl v počátcích své tvorby koncipován jako pomůcka pro řešení jistých problémových úkolů. Zjednodušeně se dá říct, že každý programovací jazyk se na svou podstatu existence (tedy řešení úkolů, pro které byl stvořen) dívá z vlastního pohledu. Důkazem tohoto tvrzení jsou někdy zcela specifické postupy, které musí programátor ve dvou jazycích uskutečnit, aby vyřešil stejnou úlohu (nejjednodušším příkladem může být zapsání cyklu For ve Visual Basicu a C++). I když je každý programovací jazyk specifický, všechny jazyky disponují mnoha „standardními“ konstrukcemi (v analogii s předchozím příkladem, oba jazyky, Visual Basic i Visual C++ obsahují cyklus For). Rozvineme-li myšlenku, že každý programovací jazyk byl primárně určen na řešení jistého okruhu problémů, můžeme dojít k poznání, že jeden jazyk může být vhodnější na řešení jisté skupiny problémů, zatímco jiný jazyk si zase dobře poradí s jinou, specifickou množinou úkolů. Jestliže popojedeme v našich úvahách ještě o krok dále, objevíme samotnou myšlenku programování ve více jazycích. Posuďte sami: Proč používat na vyřešení jistého problému jazyk, ve kterém je toto řešení když ne nemožné, tak alespoň hodně obtížné? Nebylo by lepší jednoduše napsat onu kritickou část programu v jiném jazyce, který si s naším problémem umí lépe poradit?

 

Použití teorie míchání programovacích jazyků může přinést mnoho výhod:

 

Úspora času

Otázka rozřešení programátorského problému, se kterým nevíme v prostředí jednoho jazyka „ani hnout“, se v jiném jazyce může stát otázkou několika málo okamžiků.

Zlepšení výkonu

Napsání kritických částí programu v jiném, nižším, programovacím jazyku může způsobit citelné zlepšení výkonu aplikace.

Zlepšení rychlosti

S předchozím bodem se úzce váže i zlepšení rychlosti programu. V případě, že napíšeme optimalizovaný kód nižší úrovně, a ten pak využijeme ve stávající aplikaci, zlepšení rychlosti může být signifikantní.

Znovupoužitelnost programového kódu

Pokud jsme schopni napsat nízkoúrovňový kód, který později „zabalíme“ do komponenty pro další použití, nemusíme již tuto část kódu psát opět později. Jednoduše využijeme to, co již máme připravené.

 

Pro úplnost výkladu je zapotřebí vzpomenout i některé stinné stránky této teorie programování.

 

Vědomostní úroveň

Jde o úroveň znalostí a schopností, kterou musí programátor disponovat. Ne každý programátor totiž umí dobře programovat ve více jazycích. V této souvislosti není možno zapomenout na prvotní zvýšené náklady na zvýšení znalostní úrovně programátora. Může jít např. o absolvování specializovaného programátorského kurzu, nákup literatury a pod.  

Nutnost vlastnit další programovací nástroj

Pokud se rozhodnete pro programování ve více jazycích, budete pravděpodobně muset investovat do nákupu dalšího vývojového nástroje, kterého cena může značně ovlivnit váš rozpočet pro vyvíjenou aplikaci.

 

 

V dnešní případové studii budeme společně řešit jeden z nejčastějších úkolů programátora pracujícího v prostředí dvou programovacích jazyků. Půjde o vytvoření dynamicky linkované knihovny (DLL) ve Visual C++ a následně její implementace do aplikace vyvíjené ve Visual Basicu.

 

Pokud náhodou patříte mezi skupinu programátorů VB, kterým se při vyslovení názvů „C/C++“, případně „Visual C++“ udělá špatně, nemusíte se již více obávat a můžete zůstat zcela klidní. V tomto článku totiž nepředpokládám, že máte nějaké zkušenosti jak s jazykem C/C++, tak s vývojovým prostředím Visual C++. V celém článku se uplatňuje ověřená technika postupu stylem „krok za krokem“, proto se nemusíte obávat jakýchkoliv nejasností. Uvidíte, že po přečtení následujících řádků budete i vy schopni vytvořit jednoduchou DLL ve Visual C++.  

 

 

Visual Basic .NET a Visual C++ .NET

Krok 1: Tvorba dynamicky linkované knihovny (DLL) ve Visual C++ .NET

 

V následující ukázce vytvoříme standardní dynamicky linkovou knihovnu typu Win32, která bude obsahovat jednu funkci pro výpočet třetí mocniny čísla. Postupujte takto:

 

  1. Spusťte Visual Studio .NET a z nabídky File vyberte položku New a pak Project.

 

Stejného účinku můžete docílit i klepnutím na ikonu New Project na standardním panelu ikon, nebo klepnutím na tlačítko New Project v okně Start Page. Pokud okno Start Page po spuštění Visual Studia není viditelné, klepněte na nabídku Help a aktivujte položku Show Start Page.

 

  1. Okno New Project upravte podle obr. 1.

 

 

Obr. 1 – Okno pro výběr nového typu projektu

 

V levé části okna, v sekci Project Types, vyberte jako typ projektu Visual C++ Projects. V pravé části okna, v sekci Templates, vyberte položku Win32 Project. V textovém poli Name zadejte jméno pro váš nový projekt a zaškrtněte volbu Create directory for Solution, čímž zabezpečíte vytvoření samostatné složky pro vaše řešení. Když jste se změnami spokojeni, klepněte na tlačítko OK.  

 

  1. Visual C++ zobrazí okamžitě průvodce s názvem Win32 Application Wizard.
  2. Klepněte na položku Application Settings. V sekci Application Type vyberte možnost DLL (obr. 2) a nakonec klikněte na tlačítko Finish.

 

Obr. 2 – Výběr typu aplikace v průvodci

 

Visual C++ posléze vytvoří všechny nezbytné soubory, které si aplikace typu Win32 DLL vyžaduje. Seznam těchto souborů si můžete prohlédnout v Průzkumníkovi řešení (Solution Explorer). Okno Průzkumníka řešení by se mělo nacházet v pravé horní části okna Visual C++ a jeho podoba je zachycená na obr. 3.

 

 

Obr. 3 – Okno Průzkumníka řešení (Solution Explorer)

 

Nyní poklepejte na položku DLL_C++.cpp, která se nachází ve stromové struktuře pod uzlem Source Files. Visual C++ následně otevře vybraný zdrojový soubor projektu, kterého obsah pro vás zobrazí v okně pro zápis programového kódu (obr. 4).

 

 

Obr. 4 – Okno pro zápis programového kódu ve Visual C++

 

V tomto okně si můžete všimnout více věcí, které se vám (jako programátorovi VB), můžou zdát neznámé a podivné. Pojďme tedy pěkně popořádku a obsah okna si vysvětleme. Nuže, první dva řádky představují komentáře, které do kódu umístil samotný Visual C++. Zapamatujte si, že každý komentář (ve stylu jazyka C++) je uveden dvěma lomítky, které jsou symbolem pro jednořádkové komentáře. Znamená to tedy, že když uvedete v kódu dvě lomítka a za nimi text, tento je později kompilátorem chápán jako komentář a je zcela ignorován.

 

Další nejasností je pravděpodobně tento řádek:

 

#include "stdafx.h"

 

První část výrazu #include je takzvaná direktiva preprocesoru. Ta „říká“ preprocesoru, aby soubor s názvem „stdafx.h“ začlenil do programového kódu projektu. Řečeno jinými slovy, když preprocesor při své práci „narazí“ na direktivu #include, vloží obsah souboru, který tato direktiva specifikuje, do samotného programového kódu vyvíjené aplikace. Soubor „stdafx.h“, jenž tvoří druhou část výrazu, je tzv. hlavičkovým souborem.

 

Preprocesor je typem textového procesoru, který jistým způsobem modifikuje zdrojový text programu ještě před samotnou kompilací (ve skutečnosti se preprocesor používá jenom v první etapě kompilace programu).

 

Následuje definice funkce DllMain, která je vstupním bodem (entry point) do dynamické knihovny. Tuto funkci volá samotný operační systém při inicializaci a terminaci procesů a vláken. Protože v naší ukázce nebude chtít vykonávat žádné operace při uvedených činnostech, můžeme ponechat funkci DllMain v její původní podobě.

 

Ve všeobecnosti je dynamicky linkovaná knihovna naplněna funkcemi, které je možné z jejího prostředí později volat. Abyste do stávajícího kódu přidali také kód pro naší exportovanou funkci, udělejte následovní:

 

  1. Umístěte kurzor myši pod všechen programový kód (ještě přesněji pod řádek s uzavírací složenou závorkou).
  2. Zde zadejte tento fragment kódu:

 

extern "C" __declspec(dllexport) __stdcall int Mocnina(short cislo)

{

      return cislo*cislo*cislo;

}

 

Toto je zápis pro exportovanou funkci. Pod pojmem „exportovaná funkce“ se rozumí funkce, která bude v budoucnosti volána z programovacího jazyka VB .NET. Aby bylo možné tuto funkci zavolat z programu VB .NET, je zapotřebí uvedená definice funkce. Pokud odhlédneme od použití modifikátorů extern „C“, __declspec(dllexport) a volací konvence __stdcall, dostáváme se k samotné funkci. Její název je „Mocnina“ a jak je vidět, funkce má jeden parametr, kterým je proměnná typu short s názvem „cislo“.

 

V jazyce C++ se proměnné deklarují jinak než je to ve Visual Basicu. Zde je zapotřebí nejdříve uvést datový typ proměnné a až poté samotné jméno proměnné.

 

Protože jde o parametr funkce, je nutno jej uzavřít do kulatých závorek. Návratová hodnota funkce je specifikována před jménem funkce; z uvedeného příkladu vidíme, že půjde o návratovou hodnotou typu integer, jak specifikuje klíčové slovo int. Tělo každé funkce v prostředí jazyka C/C++ je uzavřeno do složených závorek. Tělem funkce se rozumí příkazy, které se mají provést tehdy, je-li funkce zavolána. V našem případě si můžete všimnout, že v těle funkce je jenom jediný příkaz. Tento příkaz vypočte třetí mocninu čísla, kterou funkce při dokončení své práce vrací. Všechno, co následuje za klíčovým slovem return představuje návratovou hodnotu funkce. Konečně, každý příkaz v jazyku C/C++ je ukončen nikoliv koncem řádku, nýbrž středníkem.

 

  1. Aby bylo později možné volat exportovanou funkci z Visual Basicu, je nutné do projektu s DLL knihovnou začlenit tzv. definiční soubor (.DEF), který explicitně popisuje seznam funkcí určených na export. Vyberte tedy nabídku Project a klepněte na položku Add New Item. Objeví se dialogové okno, ve kterém označte položku DEF File (obr. 5). Po zapsání jména souboru stiskněte tlačítko Open.

 

 

Obr. 5 – Výběr definičního souboru pro export funkce z knihovny DLL

 

  1. Visual C++ ihned vytvoří a zobrazí definiční soubor. V souboru by se měl nacházet jeden řádek, ve kterém je zapsáno požadované slovo LIBRARY, které je následováno jménem dynamické knihovny.
  2. Do definičního souboru přidejte další řádek, ve kterém pomocí klíčového slova EXPORTS určíte funkce, které se mají exportovat (jinými slovy, které mají být „viditelné“ z externího programu). V našem případě jde o jedinou funkci s názvem „Mocnina“. Výslednou podobu definičního souboru můžete vidět na obr. 6.

 

Při zápisu jména funkce mějte na paměti, že Visual C++ je „case sensitive“, tedy rozlišuje malá a velká písmena ve slovech. Pokud byste zadali místo řetězce „Mocnina“ řetězec „mocnina“, jednalo by se o zcela jinou funkci. 

 

 

Obr. 6 – Výslední podoba souboru DEF

 

Všimněte si hvězdičky, která se nachází v záložce za jménem DEF souboru na obr. 6. Tímto způsobem vás Visual C++ upozorňuje na skutečnost, že obsah souboru se změnil od té doby, co jste tento soubor naposled uložili.

 

  1. Vyberte nabídku File a ukažte na příkaz Save All, nebo klikněte na stejnojmennou ikonu na panelu tlačítek.
  2. Dále aktivujte nabídku Build a vyberte příkaz Build Solution, anebo opět klepněte na příslušné tlačítko.

 

Po vydání příkazu na sestavení aplikace Visual C++ zkompiluje všechny nezbytné soubory a vybuduje jedinou dynamickou knihovnu. Jestliže vše proběhlo tak, jak mělo, ve spodním panelu uvidíte text „Build succeeded“. Výborně, dokázali jste vytvořit svou první dynamicky linkovanou knihovnu!

 

Podíváte-li se do složky vašich projektů a otevřete složku Debug právě vytvořeného projektu, můžete vidět knihovnu DLL v celé její kráse tak, jak ji znázorňuje obr. 7.

 

 

Obr. 7 – Vytvořená dynamicky linkovaná knihovna (DLL)

 

Abyste nemuseli později zadávat celou cestu k vaší knihovně DLL, zkopírujte ji do systémové složky Windows (Windows\System).

 

 

Visual Basic .NET a Visual C++ .NET

Krok 2: Využití dynamické knihovny ve Visual Basicu .NET

 

Pro předvedení možností knihovny DLL v prostředí VB nejdříve přidáme do stávajícího projektu standardní projekt VB. Postupujte takto:

 

  1. Zvolte nabídku File, příkaz New a pak Project.
  2. V okně pro výběr projektu vyberte projekty VB (Visual Basic Projects) a jako konkrétní typ projektu vyberte Windows Application. Dále vyberte volbu Add to Solution, čímž přidáte projekt VB k již stávajícímu projektu Visual C++. Nakonec nový projekt pojmenujte a klepněte na tlačítko OK.
  3. Visual Basic .NET vytvoří všechny nezbytné soubory pro nový projekt, který následně přidá do již vytvořeného řešení.
  4. Přidejte do projektu Visual Basicu standardní modul. Uděláte to tak, že vyberete nabídku Project a klikněte na položku Add New Item. V objevivším se okně vyberte ikonu modulu a jeho vytvoření potvrďte stisknutím tlačítka OK. Do projektu VB se automaticky přidá modul. Poklepejte na ikonu nového modulu v Průzkumníkovi řešení, čímž si vyžádáte otevření okna pro zápis kódu. Do modulu umístěte deklaraci exportované funkce z naší DLL:

 

      Public Declare Function Mocnina Lib "DLL_C++.dll" _

(ByVal cislo As Short) As Integer

 

  1. Pokračujte tím, že na formulář přidáte jednu instanci ovládacího prvku Button. Na vytvořenou instanci poklepejte, čímž otevřete okno pro zápis programového kódu. Do obsluhy události Click tlačítka doplňte tento řádek kódu:

 

MessageBox.Show(Mocnina(3).ToString)

 

  1. Uložte projekt VB klepnutím na tlačítko Save All.
  2. V Průzkumníkovi řešení klepněte pravým tlačítkem myši na název projektu VB a z kontextové nabídky vyberte položku Set as Startup Project.
  3. Klikněte na tlačítko Start, případně stiskněte klávesu F5 pro spuštění projektu.

 

Jakmile klepnete na tlačítko, VB .NET zavolá exportovanou funkci s názvem „Mocnina“, která vypočte třetí mocninu čísla 3 a návratovou hodnotu zobrazí v okně zprávy (obr. 8).

 

 

Obr. 8 – Finální podoba spolupráce aplikace VB a knihovny DLL

 

Výborně, dynamicky linkovaná knihovna odvádí svou práci na jedničku!

 

Abyste zmenšili velikost výslední knihovny DLL, můžete ji také sestavit v distribučním provedení. V tomto provedení se kód plně optimalizuje a rovněž se z něj odstraní informace, které jsou určeny pouze pro proces odlaďování knihovny. V prostředí Visual C++ udělejte následovní:

 

  1. Z nabídky Build vyberte příkaz Configuration Manager. Objeví se dialogové okno, ve kterém určíte, aby se knihovna DLL kompilovala v provedení, které bude určené pro distribuci. Z otevíracího seznamu v sloupci Configuration vyberte položku Release (obr. 9).  

 

 

Obr. 9 – Výběr distribučního provedení knihovny DLL v okně Configuration Manager

 

  1. Klepněte na tlačítko Close a z nabídky Build vyberte položku Build DLL_C++. 

 

Visual C++ uskuteční sestavení dynamicky linkované knihovny a ve stávající složce projektu vytvoří další složku s názvem „Release“. Ve složce „Release“ se nachází knihovna DLL, připravená na distribuční proces. Abyste měli lepší představu o velikosti knihovny DLL, podívejte se na obr. 10, který znázorňuje velikost knihovny DLL určené pro odlaďování a pro distribuci.

 

 

Obr. 10 – Porovnání velikosti variant provedení knihovny DLL

 

 

Věřím, že vás uvedená problematika zaujala a rozšířila vaše programátorské znalosti.

 

 

Ján Hanák