passing object from c# to c++ - visual-c++

I've been working on a prototype code application that runs in C# and uses classes and functions from older C++ code (in the form of an imported DLL). The code requirement is to pass in a class object to the unmanaged C++ DLL (from C#) and have it be stored/modified for retrieval later by the C# application. Here's the code I have so far...
Simple C++ DLL Class:
EXPORT_DLL int init(MyInitParams *initparams);
C++ DLL Functions:
struct MyInitParams {
public:
int _np;
int _nm;
int type;
double *CV_Weight;}
in c# DLL
[DllImport("NEWUSEMPC", CallingConvention = CallingConvention.Cdecl, EntryPoint = "init")]
public static extern int init(InitParams parameters);
in c# class
class InitParams
{
public int _np;
public int _nm;
public int type;
public double[] CV_Weight;}

If you own the code of the c++ dll it would be a lot more convenient for you to include it in your solution, and create an interop between c# and c++ using managed c++ as a translation layer. Be aware, that the managed c++ layer should only do the translation of data and invoke the native method, and literally nothing else, because managed c++ is designed only as a bridge between the native and managed world.
You can also use mixed debugger to check out what is happening in both managed and unmanaged code in debug to take a look on the variables, so that you can see what's missing.
I personally would discourage the use of platform invoke instead of an interop class, because the latter is a lot cleaner and is easier to maintain later on.

Related

ObjectQuery extensions from managed C++/CLI

I'm trying to move a project over to using Entity Framework, but to make it more fun, the project is in C++/CLR.
I've got a query
ObjectQuery<myData::Facility^>^ facQ = myContext->FacilitySet;
and I want to do this
int n = facQ.Count()
But I can't because c++ doesn't recognise extension methods using C# syntax. facQ->Count() doesn't work.
Using C# extension methods from managed C++/CLI shows the answer for user-defined extensions; but in this case, the extension is part of the .NET framework http://msdn.microsoft.com/en-us/library/bb349034%28v=vs.90%29.aspx.
Any ideas?
(I'm using visual studio 2008, and .NET 3.5).
System::Data::Objects::ObjectQuery implements IEnumerable<T>. The Count() method you see in C# is from the System::Linq::Enumerable class.
using namespace System::Linq;
int n = Enumerable::Count(facQ);
Also see this answer, which shows a couple examples of calling other extension methods in that class.

.NET Reflector - Reflexil, Change private to public

I have an assembly loaded into .NET reflector and I have the reflexil addin.
I found a method in the assembly but it's private. Copying the whole method to my code is too much work because it uses many other methods in the assembly. I just want to change
private void Check(string Proxy, int Port)
to
public void Check(string Proxy, int Port)
So I can use it in my code. Does anybody know how to change it and how to save the fixed assembly after that?
Kirk
Instead of re-writing the assembly, consider using Reflection from your code to invoke the private method dynamically, see:
How do I use reflection to invoke a private method?

call unmanaged C++ code from C# using pinvoke

I have a unmanaged C++ dll for which I do not have access to code but have all methods declarations for.
Lets for simplicity say that .h looks like this:
#include <iostream>
#ifndef NUMERIC_LIBRARY
#define NUMERIC_LIBRARY
class Numeric
{
public:
Numeric();
int Add(int a, int b);
~Numeric();
};
#endif
and method implementation in .cpp file
int Numeric::Add(int a, int b)
{
return (a + b);
}
I simply want to call the add function from C++ in my C# code:
namespace UnmanagedTester
{
class Program
{
[DllImport(#"C:\CPP and CSharp Project\UnmanagedNumeric\Debug\numeric.dll", EntryPoint = "Add")]
public static extern int Add(int a, int b);
static void Main(string[] args)
{
int sum = Add(2, 3);
Console.WriteLine(sum);
}
}
}
After trying to execute I have the following error:
Unable to find an entry point named 'Add' in DLL 'C:\CPP and CSharp Project\UnmanagedNumeric\Debug\numeric.dll'.
I CAN NOT change C++ code. Have no idea what is going wrong.
Appreciate your help.
Using PInvoke you can only call global functions exported from Dll. To use exported C++ classes, you need to write C++/CLI wrapper. This is C++/CLI Class Library project, which exposes pure .NET interface, internally it is linked to unmanaged C++ Dll, instantiates a class from this Dll and calls its methods.
Edit: you can start from this: http://www.codeproject.com/KB/mcpp/quickcppcli.aspx#A8
If you need to create a wrapper, take a look at swig.org. It will generate one for most high level language like C#.
I just came across this program a few minutes ago while working the same problem that you are.
To use a class from native C++ from C# you need a C++/CLi wrapper in between, as mentioned by by previous answers. To actually do that, it is not very straight forward. Here is I link that tell you how to do it at a high level: C++/CLI wrapper for native C++ to use as reference in C#.
If you are quite new to this (like me), you might stumble on 1) -- the linking part. To solve that, you can see how I did here (see my question portion): Link error linking from managed to unmanaged C++ despite linking to .lib file with exported symbols

error calling managed code from unmanaged in C++/CLI

I'm writing a "driver" for a program, the driver communicates with some devices on network. I already have C# software working with the devices, so the plan is to reuse code.
So the driver dll is really an interop between program and and already availible assemblies, it's written in C++/CLI. The program calls methods described in interface, the interop dll calls C# code, that is how I see it.
I implement methods to be called by program using #pragma unmanaged
DeviceSearch::DeviceSearch(IDeviceSearchHandler* handler):m_handler(handler)
{
ManagedWrapper mw;
mw.Init();
}
ManagedWrapper is implemented in managed code, obviously
void ManagedWrapper::Init()
{
//some code
}
However, the problem rises here. If the Init() is empty or calls methods/classes defined in C++, it's working ok. However, if I try to call the C# code (which is referenced using #using , where Facade.dll is the C# dll which performs some functions), I get access violation exception right when mw.Init() is called, not even within it.
Am I missing something really obvious I should do to make the interop work? Most information in the net just tells that it should "just work"
See if this helps:
According to How can i use a C# dll in a Win32 C++ project?
"Define an abstract interface class in your native C++ code, then create a concrete subclass inside the managed C++ DLL. Call into your C# objects in the method implementations.
Finally, export a factory function that will instantiate the implementation class and return a base-class pointer that your native code can use."

Can you force MonoTouch to include an unreferenced assembly in its static compilation?

I have a MonoTouch app that dynamically instantiates a class (using Type.GetType()) at runtime. The class is in an assembly that is not referenced anywhere else in the app, so the MonoTouch static compiler thinks that the assembly isn't used and ignores the assembly when it compiles the app. If I add a reference to the class in the app, then the compiler includes the assembly and the call to Type.GetType() works fine:
MyAssembly a;
I would prefer to just tell the compiler to always include all the assemblies listed in the project's "References" when it compiles the app. Is this possible?
Thanks,
-Tom B.
You will have to change your project's Linker behavior from "Link all assemblies" to "Link SDK assemblies only".
The other solution, if you have the project code that assembly was created with, is to mark the class you want to use with the PreserveAttribute.
Were you able to figure this out yet? If not, I had a similar problem: Is there a way to force MonoDevelop to build/load an assembly?
As I understand it, that's just how the C# compiler works. I was able to get around this by adding a custom pre-build step that scripts a class into the referencing assembly that includes dummy references to the unreferenced assemblies, like so:
using System;
namespace MyNamespace
{
public static class Referencer
{
Type t;
//These lines are scripted one per class in the unreferenced assemblies
//You should only need one per assembly, but I don't think more hurts.
t = typeof(Namespace1.Class1);
t = typeof(Namespace2.Class2);
...
t = typeof(NamespaceN.ClassN);
}
}

Resources