Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

How can I call a managed CLR/C++ routine from unmanaged C++?

Posted on 2014-11-02
7
Medium Priority
?
736 Views
Last Modified: 2014-11-08
I'm having a linking problem that looks just like this one: http://www.experts-exchange.com/Programming/Languages/.NET/Q_23332235.html that unfortunately didn't end up getting resolved.

I have code in an unmanaged C++ project that needs to call code in a C# project (i.e, managed code).  To that end I have created a 'bridge' project in CLR/C++ which will wrap the C# code and give the unmanaged C++ code something to call into.  There are several descriptions of how to do this on the web and I've been working through this one stackoverflow.com/questions/1827102/managed-c-to-form-a-bridge-between-c-sharp-and-c.

Bridge Project (C++/CLR)
// This is the main DLL file and is named MixedModeDLL.cpp
#pragma once
#include "stdafx.h"
#include "MixedModeDLL.h"
#include "CppInterface.h"

double CalculateProduct(double x, double y)
{
	ManagedClass^ t = gcnew ManagedClass();
	double z = t->multiplyTwoValues(x, y);

	return z;
}

Open in new window


That's it.  The header file CppInterface.h is pretty simple.  It just exports the routine CalculateProduct which calls the C# code (via machinations in MixedModeDLL.h which I'm happy to share but seems a distraction to the problem at hand) like this:
#pragma once

extern "C" __declspec(dllexport) double CalculateProduct(double x, double y);

Open in new window


It should be noted that I have successfully called the CalculateProduct(...) routine from a C# driver program which implies that CalculateProduct(...) can be accessed by outside code (i.e., it looks like it is being exported).  I did this using this code:
private void button4_Click(object sender, EventArgs e)
{
   // Test of calling into the managed C++ (CLR) MixedModeDLL DLL.
   double h = 2.5;
   double k = 6.0;
   double p = NR.CalculateProduct(h, k);
}

Open in new window


where NR is a C# class in the driver code defined like this:
class NR
{
   [DllImport("MixedModeDLL.dll", EntryPoint = "CalculateProduct")]
   public static extern double CalculateProduct(double x, double y);
}

Open in new window


C++ Project:
In the C++ code I have a line that says the following:

extern "C" __declspec(dllexport) void testCPPcallingCS()
{
   double z = CalculateProduct(4.9, 3.2);
}

Open in new window


(Note: (the export here is so that my C++ driver program can get access to testCPPcallingCS())

testCPPcallingCS() is defined in a module that includes a #include statement for  header file that mirrors CppInterface.h described above; where that one says export, this one says import.  That is:

#pragma once

 extern "C" __declspec(dllimport) double CalculateProduct(double x, double y);

Open in new window


The compiler has no problem with this, but the linker gets fussy.  It reports two errors:
error LNK 2019: unresolved external symbol __imp_CalculateProduct referenced in function testCPPcallingCS
error LNK1120: 1 unresolved externals

It almost looks like the name of the CalculateProduct routine has been decorated with a prefix of __imp_.   I have checked that all of the expected DLLs are in the output directory (...\Driver_CPP\x64\Debug) and that the *.lib of the 'Bridge' CLR/C++ code (i.e., MixedModeDLL.lib) is located in the same directory.  In the aforementioned link the author says to insure that the linker is told to 'use the generated .lib file when linking'.  I have checked the Properties of MixedModeDLL and the native C++ project and see nothing that implies to me that the .lib file is not being used.

I'm developing using Microsoft Visual Studio 2010 (my C# driver routine is written in MSVS 2012) on a Windows 7 computer.  MixedModeDLL and the unmanaged C++ DLL are targeted to an x64 platform.
0
Comment
Question by:e_livesay
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
7 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 40418642
COM/Interop is usually the way to go if you need to call .NET code from unmanaged code. See http://www.codeproject.com/Articles/12673/Calling-Managed-NET-C-COM-Objects-from-Unmanaged-C ("Calling Managed .NET C# COM Objects from Unmanaged C++ Code")
0
 

Author Comment

by:e_livesay
ID: 40418651
I've seen references to COM but was hoping to avoid all of the overhead associated with it.  Also, I'm now very interested to figure out what I'm doing wrong.  The method that I'm trying to implement has been reported to work in various locations ( http://stackoverflow.com/questions/1827102/managed-c-to-form-a-bridge-between-c-sharp-and-c as well as here http://www.codeproject.com/Tips/695387/Calling-Csharp-NET-methods-from-unmanaged-C-Cplusp).

It seems that the only missing component is the importation of the function definition into my unmanaged C++ DLL.
0
 
LVL 86

Expert Comment

by:jkr
ID: 40418755
>>but was hoping to avoid all of the overhead associated with it.

Um, sorry to say so, but at the moment the overhead is at your side ;o)

It (at least to me) seems a lot easier to just use a COM IF comprised of a single method, especially since the price for that on the C# side is minimal at best and the C++ side is sort of straightfoward for the same reason, espcially if you can make use of ATL helpers in that context.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 35

Expert Comment

by:sarabande
ID: 40419159
It almost looks like the name of the CalculateProduct routine has been decorated with a prefix of __imp_.
it is more that CalculateProduct is managed code which could be called from C# or managed c++ or mixed-code c++ dlls but not from (pure) unmanaged code.

though the export definitions are valid, the linker was unable to provide a bridge from unmanaged to managed which would be required when calling the CalculateProduct from unmanaged.

as I don't have done much with mixed-code, I am not quite sure whether the problem could be solved with your approach. but you could try to add an exported (unmanaged)  wrapper function to the mixed-code dll which calls the CalculateProduct rather than to exporting the CalculateProduct itself.

that way the mixed-code dll should provide the bridge functionality needed.

Sara
0
 

Accepted Solution

by:
e_livesay earned 0 total points
ID: 40420282
Turns out I hadn't told the the linker to look in the *.lib file.  I changed the import code from this:
#pragma once
extern "C" __declspec(dllimport) double CalculateProduct(double x, double y);

Open in new window

to this:
#pragma once
#pragma comment (lib, "C:\\FullPath\\Driver_CPP\\x64\\Debug\\MixedModeDLL.lib")
extern "C" __declspec(dllimport) double CalculateProduct(double x, double y);

Open in new window

and the code now works.
0
 

Author Comment

by:e_livesay
ID: 40420289
I found this useful when figuring out the linker issue:
stackoverflow.com/questions/7611198/microsoft-visual-studio-2010-adding-lib-files-in-this-version
0
 

Author Closing Comment

by:e_livesay
ID: 40430070
The other supplied answers suggested that I use COM or that I add a wrapper function.  While the use of COM was a reasonable way forward I did not end up doing it.  Nor did I add a wrapper function.  After looking at my own code again I found out what was wrong with it and fixed it myself based on a comment that I'd made earlier in the conversation surrounding this Question (i.e., related to the __imp_ prefix reported by the linker).
0

Featured Post

PowerShell Core for Advanced Linux Administrators

Understand advanced principals around Powershell Core with a focus on the Linux Administrator.  This course covers how to administer numerous environments across multiple platforms including Linux, Azure, AWS, and Google Cloud from a single shell instance.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

664 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question