Tag Archives: C++

Using .Net assemblies in your WIN32 application

Imagine that you’ve got an extensive codebase using WIN32/MFC and don’t want to give that up but on the other hand you’d like to take advantage of DOTNET classes then here’s a simple solution: First we write an Interface and an Implementation with C# as following:

public interface IQuoteClient {
  String getQuote();
  Boolean setQuote(String quote);
}

public class QuoteClient : IQuoteClient {
  // COM requires a parameterless constructor
  public QuoteClient() { ; }
  public string getQuote() { return String.Format"quote";}
  public bool setQuote(string quote) { return true; }
}

Go the project Properties and check the “Make assembly COM-Visible” box which you find in the Application tab, Assembly Information. Then you go to the Build tab and check “Register for COM interop” box and at the Signing tab you check the “Sign the assembly” box and assign a key. Build the project.

Now we have to extract a typelibrary, register the typelibrary and install it in the global assembly cache. Open a Visual Studio 2005 Command Prompt and go to your project\bin\Debug directory. Type the following commands:

tlbexp QuoteClient.dll
regasm QuoteClient.dll /tlb:QuoteClient.tlb
gacutil /i QuoteClient.dll

Now you can import the classes in this assembly from your WIN32 application as following:

#import "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.tlb"
#import "D:\projects\Test\QuoteClient\bin\Debug\ClientLibrary.tlb" no_namespace named_guids

And you can use them just like any other COM component:

CoInitialize(NULL);

IQuoteClient *qc = NULL;
HRESULT hr = CoCreateInstance(
  CLSID_QuoteClient,
  NULL,
  CLSCTX_INPROC_SERVER,
  IID_IQuoteClient,
  reinterpret_cast<void**>(&qc)
);

if (SUCCEEDED(hr)) {
  cout << "Quote: " << qc->getQuote() << endl;
  qc->Release();
  qc = NULL;
}

CoUninitialize();

More marshalling…

This snippet uses GetPrivateProfileString that is available in kernel32.dll. Apparently microsoft has decided to remove this useful function from the dotnet api.

[DllImport("kernel32", SetLastError=true)]
extern int GetPrivateProfileString(
  String ^pSection,
  String ^pKey,
  String ^pDefault,
  StringBuilder ^pValue,
  int pBufferLen,
  String ^pFile
);

StringBuilder ^buf = gcnew StringBuilder(256);
GetPrivateProfileString(
  "logsection",
  "file",
  "default",
  buf,
  buf->Capacity,
  "example.ini"
);

std::string _log_file = new string(
  (char*) Marshal::StringToHGlobalAnsi(logf).ToPointer()
);

Reading unmanaged structs with .NET

Last week i’ve spend a lot of time studying System::Runtime::InteropServices. It took me a while to figure out how i could read unmanaged structs with .NET System::IO. Here is a bit of sample code (Should be obvious enough to write a template or generic class for all sorts of structs, just like i did at the office)

typedef struct {
  char name[9];
  int name;
  double sterr;
} TEST;

FileStream ^f = gcnew FileStream("C:\\TEST.DAT", FileMode::Open, FileAccess::ReadWrite);
BinaryReader ^r = gcnew BinaryReader(f);
array<byte> ^buf = r->ReadBytes(sizeof(TEST));
TEST test;
Marshal::Copy(buf, 0, (IntPtr) &test, sizeof(TEST));

Preparing for my internship

Only two more days before my internship starts. I’m a bit nervous and excited to dive into this adventure. Today i decided to fresh my knowledge of (MS)-C++ a bit up. I’ve read a tutorial on function pointers and naming conventions. A couple of weeks ago i already had a look at pointers to member functions.

#include <iostream>
using namespace std;

void customcallback() {
        cout << "running custom callback" << endl;
}

typedef int (*method)(int, int);

int sum(int a, int b) {
        return a + b;
}

method dosum() {
        return &sum;
}

int main() {
        void (*plugin)() = NULL;
        plugin = &customcallback;
        plugin();

        method mymethod = dosum();
        cout << mymethod(10, 4) << endl;

        return 0;
}

A Unix daemon

Today i’ve written a daemon that communicates with the Netsize SMS Gateway. The daemon sources are available for download. You will have to implement your void getCode(double number, char * code) method yourself though.

daemon