5

PLEASE SEE UPDATE BELOW

(RESOLVED) Also I have extended this into a second question here Implement a C# DLL COM File In Unmanaged C++ Program

I have researched this to the end of the internet without finding a real, understandable, human example of how to do this.

I have a C# DLL that encrypts and decrypts text.

I don't want to / don't have the intellectual capability to rewrite this in C++ un-managed code. So instead I created a C++/CLR class that interfaces with the C# dll.

NOW I need to know how to call the managed C++ from my unmanaged code.

Here is my managed code and it is verified that it works

// clrTest.cpp : main project file.

#include "cSharpRiJHarn"
#include "stdafx.h"
#include <string>
#include <stdio.h>

using namespace cSharpRiJHarn;
using namespace System;


String^ Encrypt(String ^s)
{
    return  RijndaelLink::encrypt(s);   
}


String^ Decrypt(String ^s)
{
    return  RijndaelLink::decrpyt(s);   
}

int main()
{   
     //Console::WriteLine(Encrypt("It Works"));

     //Console::WriteLine(Decrypt(Encrypt("It Works")));

     //Console::ReadLine();
     return 0;
}

Now ONCE AGAIN I HAVE researched this.

I have seen allllllll the bad/overly complicated explanations

I know I need to use something called COM or Interop

I don't know how this works and I am just looking for a very simple explanation.

Thanks for the help.

UPDATE

I have turned the C# DLL into a COM File

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace cSharpRiJHarn
{
    [Guid("GuiD CODE REMOVED")]
    public interface DBCOM_Interface
    {
        [DispId(1)]
        String encrypt(string s);
        [DispId(2)]
        String decrpyt(string s);
    }

    [Guid("GuiD CODE REMOVED"),
    InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface DBCOM_Events
    {
    }

    [Guid("GuiD CODE REMOVED"),
    ClassInterface(ClassInterfaceType.None),
    ComSourceInterfaces(typeof(DBCOM_Events))]
    public class RijndaelLink : DBCOM_Interface
    {
        public String encrypt(String s)
        {
            return Rijndael.EncryptString(s); 
        }
        public String decrpyt(String s)
        {
            return Rijndael.DecryptString(s);
        }
    }
}

Now I am just need to know how to implement this in unmanaged C++... I have tried both adding just the files to the C++ project and also adding the entire cSharpRiJHarn Project to this solution. Neither work.

#import "cSharpRiJHarn" 
#include "stdafx.h"
#include <string>
#include <stdio.h>
#include <iostream>
//using namespace cSharpRiJHarn;


int main(){

    cSharpRiJHarn::RijndaelLink::encrypt("It works");
    char ch;
    std::cin>>ch;
    return 0;
}

This is one of the errors I am getting.

Error 6 error C2653: 'cSharpRiJHarn' : is not a class or namespace name

and

Error 8 IntelliSense: cannot open source file "C:/.../.../Documents/Visual Studio 2010/Projects/unmannagedCPPExample/unmannagedCPPExample/Debug/cSharpRiJHarn.tlh" c:......\documents\visual studio 2010\projects\unmannagedcppexample\unmannagedcppexample\unmannagedcppexample.cpp

Community
  • 1
  • 1
DotNetRussell
  • 9,716
  • 10
  • 56
  • 111
  • Better find a nonmanaged implementation of AES/Rijndael. There's one one in Microsoft CryptoAPI. It'd be cleaner. – Seva Alekseyev Apr 02 '13 at 19:47
  • Robert Giesecke's UnmanagedExports does what you ask for. – David Heffernan Apr 02 '13 at 20:05
  • This is reather easy to understand and implement: http://blogs.microsoft.co.il/blogs/sasha/archive/2008/02/16/net-to-c-bridge.aspx you probably don't even need the dllexport part. – stijn Apr 02 '13 at 20:06

2 Answers2

2

You could use the cool C++ Marshaling library provided by Microsoft, something like this:

#include "cSharpRiJHarn"
#include "stdafx.h"
#include <string>
#include <stdio.h>
#include "msclr\marshal_cppstd.h" // marshaling library

using namespace cSharpRiJHarn;
using namespace System;
using namespace msclr::interop; // marshaling library

std::wstring Encrypt(std::wstring s)
{
    return marshal_as<std::wstring>(RijndaelLink::encrypt(marshal_as<String^>(s)));
}

std::wstring Decrypt(std::wstring s)
{
    return marshal_as<std::wstring>(RijndaelLink::decrypt(marshal_as<String^>(s)));
}
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • I put this in my unmannaged code file and there is like 60 errors. I think it has to do with References. Do I need to add my managed code to this solution? Is there anything else I have to do to Reference this? When I right click on my project and try and add references it says that I cant. – DotNetRussell Apr 03 '13 at 12:20
  • This should compile fine if your initial code was compiling fine as well. Is this the case? – Simon Mourier Apr 03 '13 at 12:56
  • My C# DLL Compiles fine. The Managed C++ Project compiles fine and runs fine. When I create an unmanaged C++ project, put in your code, add the other projects and try and compile it doesn't run. It keeps saying that there is an error in the marshal.h file so I think there is a reference error somewhere. OR I am implementing it all together wrong. – DotNetRussell Apr 03 '13 at 13:05
  • This is one of them 14 IntelliSense: this declaration has no storage class or type specifier c:\program files (x86)\microsoft visual studio 10.0\vc\include\msclr\marshal.h 185 1 – DotNetRussell Apr 03 '13 at 13:17
  • Oh, when you said "how to call the managed C++ from my unmanaged code", I thought you would put the unmanaged C++ code in the same project as the managed C++ code (that's what my code does). If it's an external unmanaged DLL, then you need COM or P/Invoke (DLL Export <-> DLL Import with something as UnmanagedExports, as David Heffernan pointed out). In this case, you don't really need the intermediary managed C++ project. – Simon Mourier Apr 03 '13 at 13:20
  • Okay so when I included all of my stuff into the Unmanaged project all of the errors relating to that seem to have gone. They're is still about 50+ errors pointing to the marshal.h file though. – DotNetRussell Apr 03 '13 at 13:27
  • You can't put managed C++ code in an unmanaged C++ project. It's the other way. Put all your C++ stuff in a managed C++ project. – Simon Mourier Apr 03 '13 at 13:29
  • Oh I can't do that. The program is hundreds of thousands of lines of code. It can not be altered and must remain unmannaged. I need a simple solution to plug it into my managed code. – DotNetRussell Apr 03 '13 at 13:30
  • Yes, that's the issue, so you need either COM (expose .NET code as COM Object like this http://www.codeproject.com/Articles/7859/Building-COM-Objects-in-C ) or P/Invoke (expose DLL Exports to your .NET code). – Simon Mourier Apr 03 '13 at 13:36
  • So I am going through the COM one and it seems simple enough thus far. I just can't figure out where to stick this command in my C# dll sn -k Database_COM_Key.snk – DotNetRussell Apr 03 '13 at 13:56
  • This would need another question – Simon Mourier Apr 03 '13 at 13:57
  • The article doesn't full explain how to implement it into your C++ code. – DotNetRussell Apr 03 '13 at 14:07
0

First, your methods receive and return a String^ which is a managed object. Unmanaged code does not know this type, and cannot create such object. So, you will need to wrap the function call such that the function marshal the managed type to something that the unmanaged code can understand.

After that, you can add the DllExport attribute to the managed method, as discussed here.

Community
  • 1
  • 1
Akobold
  • 936
  • 8
  • 25