Wednesday, July 26, 2006

Ako som si v C# zavolal na pomoc C++

Včera som vytvátral interpret vymysleného jazyka MicroC. Vytvoril som si lexer pomocou C# Lexer, parser pomocou Jay a už stačilo vytvoriť len interpret, keď som v tom narazil na problém nedostatočnej počiatočnej analýzy. MicroC totiž používa na formátovanie reťazov C++ zápis (napr. "%d", "%5i" atd.). Ako ale tento C++ zápis interpretovať v C#, v ktorom sa na formátovanie reťazcov používa diametrálne odlišný zápis ( "{0}", "{1,5}" ) ? Mal som 2 možnosti, buď vymyslieť nejaký postup ako previesť formát z C++ do C#, alebo požiť funkciu printf z C++ v C#. Zvolil som druhú možnosť.
Najprv som si otvoril C++ projekt a vytvoril print.cpp:

#include "stdafx.h"
#include <stdio.h>
#include <stdarg.h>
extern "C"
{
__declspec(dllexport) void PrintF(const char *format, ...)
{
va_list argp;
va_start(argp, format);
vprintf (format, argp);
va_end(argp);
}
}
Funkcia PrintF je vlastne taký wrapper nad funkciou printf, ktorý berie variabilné množstvo parametrov (inšpiroval som sa tu). Projekt som skompiloval do dll knižnice ( skopíroval k binárke interpretra ) a použil v C# triede takto:
...
using System.Runtime.InteropServices;
namespace Interpreter
{
class Interpret
{
[DllImport("print.dll")]
public static extern void PrintF(string format, int arg);
[DllImport("print.dll")]
public static extern void PrintF(string format, string arg);
...
I keď je wrapper nad printf umožňuje použitie variabilného množstva parametrov jazyk MicroC vyžaduje len printf s jedným argumentom. Mohlo by sa miesto jedného parametra využiť params object args ale do printf musia vstupovať typovo správné argumenty a nejde mu poslať argument typu object. Takže pre potreby MicroC mi stačili 2 funkcie, kde jedna brala ako argument int a druhá string.

Referencie: www.codeproject.com

No comments: