How to call managed C++ methods from Un-managed C++ - c++

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

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)));
}

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.

Related

How to set TextBlock properties programmatically using C++/WinRT + WinUI 3

I've been hiding under the MFC rock for many years so I can stick to standard C++ but still write Windows Desktop apps. With C++/WinRT and WinUI 3.0, it appears that I may finally have an opportunity to modernize my code. The problem is that I know nothing about XAML or the Windows API. To fix this problem, I'm trying to work my way through Petzold's "Programming Windows, 6th ed.", replacing the C# code with C++/WinRT. When all I have to do is write XAML, all is copacetic. However, when I get to p. 24, I'm supposed to adjust TextBlock properties in code. Here's the C#:
TextBlock tb = new TextBlock();
tb.Text = "Hello, Windows 8!";
tb.FontFamily = new FontFamily("Times New Roman");
tb.FontSize = 96;
tb.FontStyle = FontStyle.Italic;
...
and here's my attempt at a replacement:
TextBlock tb;
tb.Text(L"Hello, Windows 8!");
tb.FontFamily(FontFamily(L"Times New Roman"));
tb.FontSize(96);
tb.FontStyle(FontStyle::Italic);
...
All goes well until the last line. "FontStyle::Italic" is not recognized. I have similar issues with the enums for Color and HorizontalAlignment. What is the correct way to access these enums? Have I forgotten an include or a "using"? Here's what I currently have:
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.ApplicationModel.Activation.h>
#include <winrt/Microsoft.UI.Composition.h>
#include <winrt/Microsoft.UI.Text.h>
#include <winrt/Microsoft.UI.Xaml.h>
#include <winrt/Microsoft.UI.Xaml.Controls.h>
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
#include <winrt/Microsoft.UI.Xaml.Data.h>
#include <winrt/Microsoft.UI.Xaml.Interop.h>
#include <winrt/Microsoft.UI.Xaml.Markup.h>
#include <winrt/Microsoft.UI.Xaml.Media.h>
#include <winrt/Microsoft.UI.Xaml.Navigation.h>
#include <winrt/Microsoft.UI.Xaml.Shapes.h>
and
using namespace winrt;
using namespace Microsoft::UI::Text;
using namespace Microsoft::UI::Xaml::Controls;
using namespace Microsoft::UI::Xaml::Controls::Primitives;
using namespace Microsoft::UI::Xaml::Media;
I hope there's a short answer to my long question.
To be sure, you'd need to post a little more detail (like what error message you're getting). But I'll take a guess that perhaps your code is missing a namespace qualifier. I'm just going off the UWP Windows namespace types, not the WinUI Microsoft namespace, but this code builds for me:
#include <winrt/Windows.UI.h>
#include <winrt/Windows.UI.Text.h>
#include <winrt/Windows.UI.Xaml.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Media.h>
void f()
{
winrt::Windows::UI::Xaml::Controls::TextBlock tb;
tb.Text(L"Hello");
tb.FontFamily(winrt::Windows::UI::Xaml::Media::FontFamily(L"Times New Roman"));
tb.FontSize(96);
tb.FontStyle(winrt::Windows::UI::Text::FontStyle::Italic);
tb.SelectionHighlightColor(winrt::Windows::UI::Xaml::Media::SolidColorBrush(winrt::Windows::UI::Colors::Red()));
tb.HorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment::Center);
}
As does this:
#include <winrt/Windows.UI.h>
#include <winrt/Windows.UI.Text.h>
#include <winrt/Windows.UI.Xaml.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Media.h>
using namespace winrt;
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Text;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Media;
void f()
{
TextBlock tb;
tb.Text(L"Hello");
tb.FontFamily(FontFamily(L"Times New Roman"));
tb.FontSize(96);
tb.FontStyle(FontStyle::Italic);
tb.SelectionHighlightColor(SolidColorBrush(Colors::Red()));
tb.HorizontalAlignment(HorizontalAlignment::Center);
}

Using C++ in Swift

The problem is that I don't what to write C code. I have some libraries - for example for building suffix automaton for a given text and it is much more comfortable to write this with C++. Then I want to write swift app with such class, but how to do it without writing C code and without some restrictions on using C++ code. For example
in my test.cpp I have
#include "test.h"
#include <string>
std::string hello() {
return "Hello";
}
In my bridge I have:
#include "test.h"
But there is problems with test.h.
Without using C I can't just write
#include <string>
std::string hello();

How to set Timeout in CppUnitTestFramework (C++) in Visual Studio?

How to Add Timeout for a test method in C++ in Microsoft unit testing using CppUnitTestFramework ? Most of the Solutions I found online are for CSharp projects where I can add lines like [TEST_METHOD,TIME_OUT(80)] or such ,but those are not working while testing C++ (VC++) code
I have tried the below code
#include "stdafx.h"
#include "CppUnitTest.h"
#include "../src/factorial_dp.cpp"
#include "stdio.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace spec
{
TEST_CLASS(factorial_dpSpec)
{
public:
//Add Timout for these methods
TEST_METHOD(Smallnumber)
{
int result = fact(5);
Assert::AreEqual(120, result, L"5 fact should be 120", LINE_INFO());
}
};
}
Use managed test classes.
and you can keep Timeouts in that .
[TestMethod(), Timeout(3000)]
void functionName()
{
//
}

linux eclipse c++ local namespaces and "std::"

I am trying my first c++ project and am starting small, I think. I am using Eclipse Luna and am trying to take the defaults for build env everywhere that I can. I suspect that the following is vary naive code but you gotta start somewhere.
I will eventually have 4 co/sub projects in this:
Commandline interface to a static lib
".so" lib that will be dynamically loaded into a different, thied party app and uses the static lib
A static library, mentioned above, that does the back end work of the combined app.
A utility class (for now, maybe a small lib later) for utility classes and functions common to the other sub projects.
There are a ton of questions on best practices, namespaces, etc that I would like to ask but I'll keep this short.
I have the following c++ header file:
/*
* Utilities.h
*
*/
#ifndef UTILITIES_H_
#define UTILITIES_H_
// A
namespace UserTrackingUtilities {
// B
#include <string>
#include <exception>
using namespace std;
class MyException: public std::exception {
public:
MyException(std::string ss) : s(ss) {
}
~MyException() throw () {
} // Updated
std::string s;
const char* what() const throw () {
return s.c_str();
}
};
}
#endif /* UTILITIES_H_ */
This is an exception utility (found in a different StackOverflow thread) that I am wrapping in a namespace of my own -- I think.
Eclipse is showing several issues with this header file. I'll start with one: it doesn't like the std::string construct. It doesn't matter if I put the #includes and/or the using statements at point A or B.
I've also tried this with the Linux GCC and ADT tool chains.
Pointers and advice welcome.
#include <string>
#include <exception>
Should be before
namespace UserTrackingUtilities {
BTW:
If you use using namespace std, you can write string instead of std::string.
But I suggest not to use using namespace std to avoid name conflicts and ambiguities.
Update:
Here is a minimal working example:
#include <iostream>
#include <string>
#include <exception>
namespace UserTrackingUtilities {
class MyException: public std::exception {
public:
MyException(std::string ss) : s(ss) {
}
~MyException() throw () {
} // Updated
std::string s;
const char* what() const throw () {
return s.c_str();
}
};
}
int main()
{
UserTrackingUtilities::MyException ex("Hello World");
std::cout << ex.what() << std::endl;
return 0;
}

using CString with boost string algorithms - reduce to one typedef?

I need to write some code for a MFC project, but I don't know how to get required code to work when using MFC.
I prototyped my function first just using the STL types, and boost.
STL Prototype
#include <string>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/find.hpp>
void ProtoTest()
{
std::string sText("123Hello4");
boost::iterator_range<std::string::iterator> nc_result = find_token(sText, boost::algorithm::is_alpha(), boost::algorithm ::token_compress_on);
}
Result = "Hello"
I eventually managed to get it working with MFC, however I had to supply two typedefs. I would like to do it in one, however there isn't much documentation on using the MFC port provided in boost.
#include "stdafx.h"
#include <boost\range\atl.hpp>
void Test()
{
typedef boost::range_iterator<CString>::type CString_it;
typedef boost::iterator_range<CString_it> CString_range;
CString strText("123Hello4");
CString_range r;
r = find_token(text, boost::algorithm::is_alpha(), boost::algorithm ::token_compress_on);
}
Again Result = "Hello"
Is there a single typedef I can use to hold the result of find_token, rather than needing two typdefs to achieve it.
You could just combine them
typedef boost::iterator_range<boost::range_iterator<CString>::type> CString_range;
But I don't know if that is an advantage.