Tom’s Blog

December 11, 2008

Creating a Managed Wrapper for a Lib File

Filed under: General .NET — Tom Shelton @ 12:51 pm

So, you have a lib file and it’s corresponding header file, and you need to use it from your managed application.  Now what?  Well, the simplest answer is to create a C++/CLR wrapper DLL to expose the functionality you need.  Here’s a step-by-step walk through of the process.

 

1.

The first step in this walk-through is to create lib file that we want to expose in our managed code.  To do this, create a blank Visual Studio Solution and give it a name.

  001
   

2.

Once we have a solution, lets add a C++ static library project to the solution.  To do this, go to Solution Explorer and right click on the solution.  On the context menu, select “Add -> New Project”.   This should bring up the “Add New Project” dialog.  Add a new C++ Win32 project.  Give it a name, and select OK.

  002
   

3.

When the “Win32 Application Wizard” comes up, select the “Next” button.  Under Application Type, select “Static Library”.  Also, for this example I turned off “Precompiled header”.  And select “Finish”.

  003
   

4.

Go to the Solution Explorer again, and right click on your static library project, and select “Add -> Class…”.  This will bring up the “Add Class” dialog, select “Add”.

  005
   

5.

Fill in the information in the “Generic C++ Class Wizard”.  Select “Finish”.

  006
   

6.

Modify the resulting AddClass.h file to look like this:

 
   1: #pragma once
   2:  
   3: namespace AddTwoNumbersLib
   4: {
   5:     class AddClass
   6:     {
   7:     public:
   8:         static double Add (double x, double y);
   9:     };
  10: }
   

7.

Let’s provide the implementation in AddClass.cpp:

 
   1: #include "AddClass.h"
   2:  
   3: namespace AddTwoNumbersLib
   4: {
   5:     double AddClass::Add(double x, double y)
   6:     {
   7:         return x + y;
   8:     }
   9: }
 

At this point, you should be able to successfully compile our example lib file.

   

8.

OK – we are now setup for the rest of this example.  We have a lib file and a header file that we will expose to our managed application.  To do this, we will create a new CLR class library, using C++/CLI.  So, go back to the Solution Explorer and right click on the solution.  Select “Add -> New Project…”.   In the Project Types treeview, select “Visual C++ -> CLR”.  In the Templates pane, select “Class Library”, and give it a name and select OK.

  007
   

9.

Now we need to set a couple of project properties to be able to use the lib file.  So, in Solution Explorer, right click on the ClrWrapper project and select Properties.  In the “ClrWrapper Property Pages”,  select “All Configurations” in the Configuration drop down.  Then, select “Configuration Properties -> C/C++ -> General”.  Modify the “Additional Include Directories” property, to point to the directory containing the header file for the .lib.

  008
 

Selecting the browse button will bring up the “Additional Include Directories” dialog.

  009
 

Clicking in the list at the top, will again give you a browse button that will bring up a folder browser dialog.  Use the folder browser to point to the directory where your lib files header is in.

  010
 

Select OK, then Apply in the “ClrWrapper Property Pages”.

   

10.

Now, we need to tell the linker where the lib file is.  We could do this by adding a project reference to the AddTwoNumbersLib project – but, since we are trying to simulate us only having the lib, we’ll do it the hard way!

With the “ClrWrapper Property Pages” dialog still open, “Configuration Properties -> Linker -> Input”.

  011
 

Select, “Additional Dependencies” and then the browse button that appears.  This will bring up the “Additional Dependencies” dialog.

  012
 

In the list at the top, insert the full path to the lib file (make sure it’s in quotes).

  013
 

Select OK.  And OK again on the “ClrWrapper Property Pages”.

   

11.

Now, lets create our wrapper.  Modify the following files

 

stdafx.h

 
   1: // stdafx.h : include file for standard system include files,
   2: // or project specific include files that are used frequently,
   3: // but are changed infrequently
   4:  
   5: #pragma once
   6:  
   7: #include "AddClass.h"
 

ClrWrapper.h

 
   1: // ClrWrapper.h
   2:  
   3: #pragma once
   4:  
   5: using namespace System;
   6:  
   7: namespace ClrWrapper {
   8:  
   9:     public ref class AddClass
  10:     {
  11:     public:
  12:         double Add (double x, double y);
  13:     };
  14: }
 

ClrWrapper.cpp

 
   1: // This is the main DLL file.
   2:  
   3: #include "stdafx.h"
   4:  
   5: #include "ClrWrapper.h"
   6: using namespace ClrWrapper;
   7:  
   8: double AddClass::Add(double x, double y)
   9: {
  10:     return AddTwoNumbersLib::AddClass::Add (x, y);
  11: }
 

With that done, you should be able to compile the solution.

   

12.

Now, create a managed project in the language of your choice – C# or VB, and add a reference to your the ClrWrapper.dll.  Once done, you should be able to write, compile, and run code like the following:

 

C#

 
   1: using System;
   2: using ClrWrapper;
   3:  
   4: namespace CSharpClient
   5: {
   6:     class Program
   7:     {
   8:         static void Main ( string[] args )
   9:         {
  10:             AddClass addClass = new AddClass ();
  11:  
  12:             Console.WriteLine ( addClass.Add ( 1, 2 ) );
  13:             Console.WriteLine ( addClass.Add ( 2, 2 ) );
  14:             Console.WriteLine ( addClass.Add ( 649, 1 ) );
  15:         }
  16:     }
  17: }
 

VB

 
   1: Option Explicit On
   2: Option Strict On
   3:  
   4: Imports System
   5: Imports ClrWrapper
   6:  
   7: Module Program
   8:  
   9:     Sub Main()
  10:         Dim a As New AddClass()
  11:  
  12:         Console.WriteLine(a.Add(1, 2))
  13:         Console.WriteLine(a.Add(2, 2))
  14:         Console.WriteLine(a.Add(649, 1))
  15:     End Sub
  16:  
  17: End Module

Hopefully, someone will find this useful.

December 2, 2008

A Simple Method for Evaluating Mathematical Expressions at Runtime

Filed under: General .NET — Tom Shelton @ 11:31 pm

Over the years, on the forums I frequent, the question has come up from time-to-time on how to dynamically evaluate expressions built at runtime.  Often, the suggestions range from dynamic code compilation to creating expression evaluators.  While these suggestions are not necessarily bad – they do have some drawbacks.

The main problem with dynamic code compilation, is that it is slow.  This may not be an issue if you are only going to do one or two calculations – but, if you need to perform your calculations hundreds or thousands of times, then the performance hit can become significant.  For example,  on the MSDN Visual C# forum, I was recently involved in a thread where the original poster was using dynamic compilation to evaluate expressions thousands of times and was looking for ways to speed up the process.  I suggested he try the method I am about to present here, and his processing time dropped from the approximately 7 hours to 49 seconds.  Not bad.

The other method, creating an expression evaluator, suffers from complexity.  It isn’t an easy task.  Of course, there are enough examples and pre-built libraries to perform this task that no one should have to write such a beast anymore (except maybe as an exercise).  But, why hunt down a third party library, when Microsoft has given us a built in expression evaluator?    Well, sort of. 

The expression evaluation mechanism that I am referring to is the JScript Eval method.  It seems that many do not realize that JScript is an official .NET language.  I suspect that is because the IDE has no built in support for JScript.NET.   Here is a method for creating a simple wrapper library to expose the JScript Eval method to your C# or VB program.

 

1.

Since there is no IDE support for the JScript.NET language, create and save the Evaluator.js file in the external text editor of your choice. 

 

image01

   

2.

Use the “Visual Studio 2008 Command Prompt” (Start -> Programs -> Microsoft Visual Studio 2008 -> Visual Studio Tools) to navigate to the directory that contains the Evaluator.js file.  Once there, compile the source, like this:

  image02
 

Ok, so I didn’t use the VS command prompt :)  I used the Windows PowerShell console.  I translated the bat file that the VS command prompt uses and put it in my $PROFILE.

   

3.

Now, create your Visual Basic or C# project.  Right click on your project in the Solution Explorer, and select “Add Reference…”.  On the .NET tab select Microsoft.JScript:

  image03
   

4.

Again, Right click on your project in the Solution Explorer, and select “Add Reference…”.   Select the “Browse” tab, and find and select the Evaluator.dll that we just compiled:

  image04
   

5.

Let’s write some code to use the dll.

C#
using System;
 
namespace CSharpExample
{
    class Program
    {
        static void Main ( string[] args )
        {
            string expression = string.Format ( "(Math.pow({0}, {1}) * {2}) / {3}", 50, 2, 3.5, 16.25 );
            Console.WriteLine ( Calculate ( expression ) );
        }
 
        static decimal Calculate ( string expression )
        {
            return Convert.ToDecimal ( new Evaluator ().Evaluate ( expression ) );
        }
    }
}
VB
Option Strict On
Option Explicit On
 
Module VBExample
 
    Sub Main()
        Dim expression As String = String.Format("(Math.pow({0}, {1}) * {2}) / {3}", 50, 2, 3.5, 16.25)
        Console.WriteLine(Calculate(expression))
    End Sub
 
    Function Calculate(ByVal expression As String) As Decimal
        Return Convert.ToDecimal(New Evaluator().Evaluate(expression))
    End Function
End Module

This example, is pretty simplistic – for example, the Calculate methods do not do any sort of checking to make sure that the expression passed is a valid mathematical expression.  I used the System.String.Format method to illustrate one way of getting values into an expression to be evaluated.  It should be noted that this method will not only evaluate mathematical expressions, but arbitrary JScript code.  As long as you are using a version of .NET >= 1.1, then this shouldn’t be much of an issue because unless you pass the string “unsafe” to the optional second parameter of the JScript Eval method, then the code will run in a limited security context.   If you decide to ever use the Eval method with the “unsafe” option, then you will want to make sure that all of your strings are obtained from a trusted source.

Powered by WordPress