Visualizzazione post con etichetta Code Snippets. Mostra tutti i post
Visualizzazione post con etichetta Code Snippets. Mostra tutti i post

lunedì 15 febbraio 2016

Dll and dynamic loading: tired to prototype function pointers?

Dll dynamic loading is used in a lot of contexts because give you flexibility and the power to change the code inside without touching the caller application. The base for a plugin architecture is the dynamic loading.
But this powerful has a cost in term of quantity of code to be written in order to map each of the function exported from the DLL. (yes, I know, it has also a cost in term of performance, but this is not the matter).
The code that I'm proposing is a shorter way, template based, to load dynamically a dll changing the approach used in the article called "DLLs the Dynamic Way" and based on MACROs.
My goal was to reduce the amount of the code to write, to code in more human language and to keep the advantage of the intellisense when I want to use the class wrapper fo the Dll.

Here a small unuseful Dll that exports only 2 functions:
extern "C" 
{
__declspec(dllexport) bool IsLoaded(void);
__declspec(dllexport) bool ChangeMe(unsigned char* buf, int buflen, int* lenOfBufChanged);
}
Generally, in order to load dynamically such dll you need to define 2 functions pointers in order to make your life easier when you call GetProcedureAddress/LoadLibrary and so on... Something like this
typedef short int  (__cdecl *UCharIntIntPtr)(unsigned char*, int, int*);
[...]
UCharIntIntPtr _ChangeMe;
[...]
// we assume that the Library has been correctly loaded
_ChangeMe = (UCharIntIntPtr)GetProcAddress(dllHinst,"ChangeMe");
In order to correctly use this functions in a standard class you need also to wrap them:
class MyWrapper
{
public:
       bool ChangeMe(unsigned char* buf, int buflen, int* lenOfBufChanged);
}
This approach requires that you write a lot of code, almost the same code, every time you need to load a dll. A different approach is based on my CMyLateHelper abstract class, defined in the file MyLateHelper.hpp freely downloadable here Based on templates, this class does the dirty job for you, calling LoadLibraries and mapping the functions letting you free to write a more readable code.
Using the class, step 1: derive your own class from the LateHelper.
class CDLLWrapper :
 public CMyLateHelper
{
public:
 CDLLWrapper();
 virtual ~CDLLWrapper(){};
        // to write less, you can simply copy/paste the signatures from export file of the dll
        bool ChangeMe(unsigned char* buf, int buflen, int* lenOfBufChanged);
        bool IsLoaded(void);
protected:
        virtual bool LoadFunctions(); // overload this member in order to map the functions of your dll

};
Setp 2: define your class and map the functions
CDLLWrapper::CDLLWrapper()
 :CMyLateHelper("MyDll.dll")
{
     // do some other if you need it
}

bool CDLLWrapper::LoadFunctions()
{
 try
 {
     if (!MapMemberFunction("IsLoaded"))
        return false;

     if (!MapMemberFunction("ChangeMe"))
        return false;

 }
 catch (...)
 {
  return false;
 }

 return true;
}

bool CDLLWrapper::ChangeMe(unsigned char* buf, int buflen, int* lenOfBufChanged)
{
   bool rv = false;

   try
   {
     rv = ExecuteIt("ChangeMe",buf,bufLen,lenOfBufChanged);
   }
   catch (...)
   {
     rv = false;
   }

 return rv;
}

bool CDLLWrapper::IsLoaded(void)
{
   bool rv = false;

   try
   {
     rv = ExecuteIt("IsLoaded");
   }
   catch (...)
   {
     rv = false;
   }

 return rv;
}
Now you can use the wrapper in your app. Remember to call Initialize method before to use the other member functions.
This class has been tested on Windows but only using cdecl calling convention for exported functions.
Suggestions or improvements are encouraged.
P.S. the script used to format the code has some bug displaying the template definition. Obviously the empty string added at the ned of the call of teh function MapMemberFunction are wrong.

martedì 8 settembre 2015

RouterOs: update no-ip dynamic public address

This script shows a way to update the NO-Ip.com sevice with the public ip address of a RouterOs board installed inside a lan where the box is not directly exposed to the internet.
This script is based from different resources that I have combined to reach my goal.

Change the values of the first 3 variables with your proper configuration. 
# No-IP automatic Dynamic DNS update

#--------------- Change Values in this section to match your setup ------------------

# No-IP User account info
:local noipuser "no-ipUsername"
:local noippass "password"

# Set the hostname or label of network to be updated.
# Hostnames with spaces are unsupported. Replace the value in the quotations below with your host names.
# To specify multiple hosts, separate them with commas.
:local noiphost "myhost.ddns.net"


#------------------------------------------------------------------------------------
# No more changes need

/tool fetch url="http://myip.dnsomatic.com/" mode=http dst-path=mypublicip.txt
local ip [file get mypublicip.txt contents ]
put $ip

# The update URL. Note the "\3F" is hex for question mark (?). Required since ? is a special character in commands.
:local url "http://dynupdate.no-ip.com/nic/update\3Fmyip=$ip"
:local noiphostarray
:set noiphostarray [:toarray $noiphost]
:foreach host in=$noiphostarray do={
   :log info "No-IP: Sending update for $host"
   /tool fetch url=($url . "&hostname=$host") user=$noipuser password=$noippass mode=http dst-path=("no-ip_ddns_update-" . $host . ".txt")
   :log info "No-IP: Host $host updated on No-IP with IP $ip"
}
 
Credits:
c0d3rSh3ll from Mikrotik forum.
Mikrotik Wiki page



martedì 20 novembre 2012

Calcolare Crc32 in C++

Classe per calcolare il Crc32 di un determinata porzione di bytes disponibile per il download qui.
C++ class to compute the Crc32 of a portion of bytes. Download available here.

mercoledì 10 ottobre 2012

Arrotondare un numero ad x cifre decimali

Semplice routine in C++ per arrotondare un numero float alla cifra decimale passata come parametro della routine.

float GetRounded(float numToR,int decimals)
{
    float rounded = 0.0f, decimal = 0.0f;     float plus = 0.0f, minus = 0.0f;     plus = pow(10.0,decimals);     minus = pow(10.0,-decimals);     rounded = numToR * plus;     decimal =  abs((int)rounded - rounded);     rounded = (int)rounded / plus;     if(decimal > 0.5)          rounded += minus;     return rounded; }

mercoledì 20 giugno 2012

std::string: case insensitive comparison

Breve snippet di codice che offre un possibile spunto per effettuare una comparazione fra stringhe senza tener conto della differenza maiuscole e minuscole. 
#include <string>
#include <algorithm>
using namespace std;
string a = "MastEr"; string source = "master" std::transform(a.begin(), a.end(), a.begin(), ::tolower); (a == source)  ? "Equal" : "Different";

domenica 6 novembre 2011

Un modo per stampare un DataTable in C#

Ecco una classe che implementa una possibile soluzione al problema di stampare un datatable in C# senza l'uso di strumenti reportistici di terze parti.

Dopo aver aggiunto la classe MyDataTablePrinter al progetto ecco come utilizzarla:

1) aggiungere un componente di tipo PrintDocument
2) Aggiungere l'evento PrintPage dell'oggetto PrintDocument
private void cmdPrint_Click(object sender, EventArgs e)
{
   if (SetupThePrinting(dataTable))
       MyPrintDocument.Print();
}

private bool SetupThePrinting(DataTable ds)
{
PrintDialog MyPrintDialog = new PrintDialog();
MyPrintDialog.AllowCurrentPage = false;
MyPrintDialog.AllowPrintToFile = false;
MyPrintDialog.AllowSelection = false;
MyPrintDialog.AllowSomePages = false;
MyPrintDialog.PrintToFile = false;
MyPrintDialog.ShowHelp = false;
MyPrintDialog.ShowNetwork = false;

if (MyPrintDialog.ShowDialog() != DialogResult.OK)
    return false;

MyPrintDocument.DocumentName = "Test";
MyPrintDocument.PrinterSettings = MyPrintDialog.PrinterSettings;
MyPrintDocument.DefaultPageSettings = MyPrintDialog.PrinterSettings.DefaultPageSettings;
MyPrintDocument.DefaultPageSettings.Margins =new Margins(40, 40, 40, 40);

m_MyPrinter = new MyDataTablePrinter(ds,MyPrintDocument);

m_MyPrinter.m_FooterText = DateTime.Now.ToLongDateString() + ", Firma ______________________________________________";
m_MyPrinter.m_FooterFont = new Font("Tahoma", 10, FontStyle.Regular, GraphicsUnit.Point);
m_MyPrinter.m_FooterColor = Color.Black;

m_MyPrinter.m_TitleText = "Titolo.....";
m_MyPrinter.m_TitleFont = new Font("Tahoma", 18, FontStyle.Regular, GraphicsUnit.Point);
m_MyPrinter.m_TitleColor = Color.Black;

m_MyPrinter.m_RowFont = new Font("Tahoma", 9, FontStyle.Regular, GraphicsUnit.Point);
m_MyPrinter.m_RowBackColor = Color.White;
m_MyPrinter.m_RowColor = Color.Black;

m_MyPrinter.m_headerFont = new Font("Tahoma", 8, FontStyle.Bold, GraphicsUnit.Point);
m_MyPrinter.m_HeaderColor = Color.Black;
m_MyPrinter.m_HeaderBackGroudColor = Color.LightGray;

m_MyPrinter.m_GridColor = Color.Black;

return true;
}

private void MyPrintDocument_PrintPage(object sender, PrintPageEventArgs e)
{
bool more = m_MyPrinter.DrawDataTable(e.Graphics);
if (more == true) e.HasMorePages = true; }

Potete scaricare la classe a questo indirizzo

giovedì 29 settembre 2011

Win32 C++: sapere se un'istanza del programma è già caricata

Breve esempio di una possibile soluzione al problema della ricerca di un'istanza del programma già attiva.
Il codice si basa sulla creazione di un semaforo ed il relativo check della sua esistenza al caricamento dell'applicazione. L'API Win32 in gioco è la CreateSemaphore.

Routine da chiamare nel main o nell' InitHistance della vostra applicazione:

bool AmIAlreadyActive()
{
TCHAR* szSemName = _T("MySemaphoreApp"); // utilizzare il nome che più aggrada
MyHandle=  CreateSemaphore(NULL, 0, 1, szSemName);

return (!MyHandle || (GetLastError() == ERROR_ALREADY_EXISTS)) ? true : false; 
}
MyHandle è una variabile di tipo HANDLE.
Ricordarsi di chiude l'handle al termine del programma mediante
CloseHandle(MyHandle);

martedì 27 settembre 2011

Visual basic 6: lanciare un processo esterno con CreateProcess


Breve snippet di codice per aprire un processo esterno ed aspettare che finisca il lavoro in Visual Basic 6 utilizzando l'API CreateProcess e WaitForSingleObject

Private Type STARTUPINFO
        cb As Long
        lpReserved As String
        lpDesktop As String
        lpTitle As String
        dwX As Long
        dwY As Long
        dwXSize As Long
        dwYSize As Long
        dwXCountChars As Long
        dwYCountChars As Long
        dwFillAttribute As Long
        dwFlags As Long
        wShowWindow As Integer
        cbReserved2 As Integer
        lpReserved2 As Long
        hStdInput As Long
        hStdOutput As Long
        hStdError As Long
End Type

Private Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadId As Long
End Type

Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, byVal lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function GetLastError Lib "kernel32" () As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As LongPrivate Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Const NORMAL_PRIORITY_CLASS = &H20
dwMilliseconds As Long) As Long
Private Const INFINITE = &HFFFF      '  Timeout infinito
Private Const STARTF_USESHOWWINDOW = &H1

Private Const SW_SHOW = 5

Private Sub LaunchAndWait(ByVal ppath As String, ByVal cmdLine, ByVal swWnd As Long)
On Error GoTo errLW
Dim p As Long
Dim workDir As String
Dim SI As STARTUPINFO
Dim PI As PROCESS_INFORMATION

workDir = Left$(ppath, Len(ppath) - (Len(ppath) - InStrRev(ppath, "\")))

SI.cb = Len(SI)
SI.dwFlags = STARTF_USESHOWWINDOW
SI.wShowWindow = swWnd

If Len(cmdLine) > 0 Then
    If Left$(cmdLine, 1) <> " " Then
        cmdLine = " " & cmdLine
    End If
    Debug.Print ppath & cmdLine
    p = CreateProcess(ppath, cmdLine, 0&, 0&, 0&, NORMAL_PRIORITY_CLASS, 0&, workDir, SI, PI)
Else
    Debug.Print ppath
    p = CreateProcess(vbNullString, ppath$, 0&, 0&, 0&, NORMAL_PRIORITY_CLASS, 0&, workDir, SI, PI)
End If

If p <> 0 Then
    WaitForSingleObject PI.hProcess, INFINITE
    CloseHandle PI.hProcess
    CloseHandle PI.hThread
Else
    MsgBox "Error LaunchAndWait code = " & GetLastError()
End If

Exit Sub
errLW:
Debug.Print Err.Description
End Sub