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.

November 1, 2008

Calling Managed Code from a DLL Created in Visual C++ 2008

Filed under: General .NET — Tom Shelton @ 9:57 pm

I got involved in a discussion the other day over on the MSDN Visual C# General forum, in which a poster had a situation where he needed to create a dll in C++ to extend a 3rd party application – but, he wanted to reuse some of his C# code from that dll.  So, I am putting this post together to discuss the steps I took to get this working in Visual C++ 2008.  The goal of this article is to provide a step-by-step walk through.  If you follow all the steps (and I am communicating coherently) – then you should have a working code sample at the end of this article.

Since in real life, I’m primarily a C# developer, the order I do things in might be a little different then say someone who is primarily a VB.NET developer or a C++ developer.  Don’t let that throw you,  if things are in a different order,  just search around until you find the option.

 

1.

The first step is to create a new Visual C++ solution.  Click on “File -> New -> Project…”.  This brings up the “New Project” dialog.  In the “Project Types” pane, select “Other Languages -> Visual C++ -> Win32”.  Then from the “Templates” pane on the right, select “Win32 Console Application”.  Give the project a name (I called mine CallCSharpCodeSample) and select the “OK” button.

 

step1

 

When the “Application Settings Wizard” dialog appears, select the “Finish” button. The Console project just created will become the host application to test out the dll.

2.

Add a C# Class Library project.  This library will represent the existing .NET assembly that needs to exposed via the C++ dll.  Go to Solution Explorer, and right click on the solution and select “Add -> New Project…”.  In the “Project types” pane of the “Add New Project” dialog,  select “Visual C# -> Windows”.  In the “Templates” pane select “Class Library”.  Give the library a name, and then select the “OK” button.

 

step4

3.

Rename the default Class1.cs to AddClass.cs and allow the IDE to rename your class.  Insert a method to add two integers.  Your code should look something like this:

 
   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5:  
   6: namespace CustomCSharpLib
   7: {
   8:     public class AddClass
   9:     {
  10:         public int AddTwoNumbers ( int x, int y )
  11:         {
  12:             return x + y;
  13:         }
  14:     }
  15: }

4.

Setup is now complete and you’re ready to create the dll.  Right click on the solution in Solution Explorer, select “Add -> New Project…”.  Add a new C++ Win32 project from the “Add New Project” dialog.  And give it a name and select the “OK” button.

  step7

5.

You will again be presented with the “Application Settings Wizard”.  Select the “Next” button and set the project options as shown below.  Select the “Finish” button.

  step8b

6.

When the MyDll project is created, Visual Studio adds some unneeded code to “MyDll.h” and “MyDll.cpp”.  Edit these files to look like the code below.

MyDll.h:

 
   1: // The following ifdef block is the standard way of creating macros which make exporting 
   2: // from a DLL simpler. All files within this DLL are compiled with the MYDLL_EXPORTS
   3: // symbol defined on the command line. this symbol should not be defined on any project
   4: // that uses this DLL. This way any other project whose source files include this file see 
   5: // MYDLL_API functions as being imported from a DLL, whereas this DLL sees symbols
   6: // defined with this macro as being exported.
   7: #ifdef MYDLL_EXPORTS
   8: #define MYDLL_API __declspec(dllexport)
   9: #else
  10: #define MYDLL_API __declspec(dllimport)
  11: #endif
  12:  
  13: MYDLL_API int AddTwoNumbers(const int, const int);
 

MyDll.cpp:

 
   1: // MyDll.cpp : Defines the exported functions for the DLL application.
   2: //
   3:  
   4: #include "stdafx.h"
   5: #include "MyDll.h"
   6:  
   7: using namespace CustomCSharpLib;
   8:  
   9: MYDLL_API int AddTwoNumbers(const int x, const int y)
  10: {
  11:     return x + y;
  12: }
 

At this point, everything should compile just fine.  I have purposely not changed any project settings yet to enable managed code – but don’t worry, we’ll get to that!  Let’s make sure we can actually use and call this dll from the test program first.

7.

Change the default calling convention for the MyDll project to __stdcall.  You do this by right clicking on the project in the Solution Explorer and selecting “Properties…”.  Change the “Configuration” option to “All Configurations” and then select “C/C++ -> Advanced”.  Change the “Calling Convention” entry in the property page to “__stdcall (/Gz)” and select OK.

  step10
 

I’m not sure this step is actually necessary, but __stdcall is the same calling convention used by the Windows API and will make your dll easily callable from languages such as Visual Basic 6 that can’t handle the default __cdecl calling convention.

8.

Add a module definition file to the MyDll project – this will allow us to override the default name mangling done by the compiler, and make the dll more easily callable.  Right click on the MyDll project in the Solution Explorer and select “Add -> New Item…”.

9.

In the “Templates” pane of the “Add New Item” dialog, select “Module-Definition File (.def)”.  Give it a name.  Select the “Add” button.

  step12

10.

Edit your module definition file so that it looks like this (it will have a .def extension):

 
   1: LIBRARY    "MyDll"
   2:  
   3: EXPORTS
   4:     AddTwoNumbers @1

11.

Edit your CallCSharpCodeSample.cpp file to look like this:

 
   1: // CallCSharpCodeSample.cpp : Defines the entry point for the console application.
   2: //
   3:  
   4: #include "stdafx.h"
   5: #include <iostream>
   6: #include <windows.h>
   7:  
   8: using namespace std;
   9:  
  10: // our function pointer definition
  11: typedef int (WINAPI* LPFN_ADDFUNC)(const int, const int);
  12:  
  13: int _tmain(int argc, _TCHAR* argv[])
  14: {
  15:     HMODULE hMod = LoadLibrary(_T("MyDll.dll"));
  16:  
  17:     if (hMod != NULL)
  18:     {
  19:         LPFN_ADDFUNC addFunc = (LPFN_ADDFUNC)GetProcAddress(hMod, "AddTwoNumbers");
  20:  
  21:         if (addFunc != NULL)
  22:         {
  23:             cout << addFunc(1, 2) << endl;
  24:             cout << addFunc(5, 6) << endl;
  25:             cout << addFunc(100, 10024) << endl;
  26:         }
  27:         else
  28:         {
  29:             cout << "Failed to load function AddTwoNumbers" << endl;
  30:         }
  31:     }
  32:     else
  33:     {
  34:         cout << "Failed to load module MyDll.dll" << endl;
  35:     }
  36:  
  37:     return 0;
  38: }
  39:  
 

At this point, assuming you’ve done everything correctly, you should be able to compile and run the application:

  step14

12.

Now that the dll and it’s test harness are in place, let’s return our attention to the MyDll project.  At this step, we are going to enable CLR support.  Right click on the MyDll project in Solution Explorer and select “Properties…”.  Set the “Configuration” option to “All Configurations”.  Select “Configuration Properties -> General” in the menu tree, and then change the “Common Language Runtime support” option in the properties pane to “Common Language Runtime Support (/clr)” and select the “OK” button.

  step15

13.

Right click on your MyDll project in the Solution Explorer and select “References…”.  When the “Property Pages” dialog appears, select the “Add New Reference…” button.

  step18a
 

In the “Add Reference” dialog, select the “Projects” tab.  Select the CustomCSharpLib project from the list.  Select OK.

  step18b
 

This will add the reference to the C# class library to your MyDll project.  Select OK on the “Property Pages” dialog.

  step18c

14.

Edit MyDll.cpp to look like this:

 
   1: // MyDll.cpp : Defines the exported functions for the DLL application.
   2: //
   3:  
   4: #include "stdafx.h"
   5: #include "MyDll.h"
   6:  
   7: using namespace CustomCSharpLib;
   8:  
   9: MYDLL_API int AddTwoNumbers(const int x, const int y)
  10: {
  11:     AddClass addClass;
  12:     return addClass.AddTwoNumbers(x, y);
  13: }
 

Then compile and run your project.  If all goes well, this is what you should see:

  step14

One thing I did learn from this, is if you are going to include any .NET related header files (such as vcclr.h) – don’t do it in “stdafx.h”.  Otherwise, this file will be included in dllmain.cpp, and you will suddenly start getting an error about needing to add /clr switch to the command line.  The reason is that DllMain can’t be a managed function – so the IDE helpfully turns off /clr for dllmain.cpp.  There is a work around for this, you can turn on the /crl option for this file in it’s properties, but then you need to surround DllMain with some preprocessor directives to prevent it from being compiled as managed code.  It seems easier to just include any of the .NET related headers in your MyDll.h and be done with it.

Well, I hope this helps someone.  If not, it was definitely a good learning experience for me.

Powered by WordPress