[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Calling a c++ dll from a C# app

Posted on 2009-04-27
11
Medium Priority
?
606 Views
Last Modified: 2012-05-06
I am missing something simple here.  I have created a roots routine from the Numerical Recipes book in a c++ class and saved it as a .dll .   That builds and I think is good.  What I am am failing to figure out is how to call it in my C# application.  It appears as though the methods in C++ are set to private but they are most definitely set to public.  I have referenced the dll file in my C# project and have used an including statement at the top and can see the namespace and the class but not the method.  The details of the C++ code have been left out for copyright /respect reasons and I don't think they are the cause of the problem here.
C++ code:
 
#include "nr3.h"
 
using namespace System;
 
namespace Numerical_Methods 
{
 
	public ref class Roots
	{
		public: 
			
			static void laguer(VecComplex_I &a, Complex &x, Int &its)
		{
			laguer code.
 
		}
 
 
 
	
			static void zroots(VecComplex_I &a, VecComplex_O &roots, const Bool &polish)
		{
			polish code for laguere.
		}
 
 
	};
}

Open in new window

0
Comment
Question by:perrytaylor
11 Comments
 
LVL 16

Expert Comment

by:CuteBug
ID: 24240829
You need to use System.Runtime.InteropServices to call a C++ dll method from C#

http://msdn.microsoft.com/en-us/magazine/cc164123.aspx
http://www.ddj.com/cpp/184406285
0
 

Author Comment

by:perrytaylor
ID: 24240848
Even if I wrote the C++ dll in .net?
0
 
LVL 19

Expert Comment

by:alb66
ID: 24240880
If you use C++ .net you don't need InteropServices.
Can you try to add a method that has all the paremeters of .NET types?
How VecComplex_I, VecComplex_O and Complex are defined?
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 19

Expert Comment

by:alb66
ID: 24240892
Try also:

static void laguer(VecComplex_I^ a, Complex^ x, Int its)
0
 

Author Comment

by:perrytaylor
ID: 24240933
VecComplex_I, VecComplex_O and Complex are all defined in nr3.h which is publicly available and I have included it below.  

static void laguer(VecComplex_I^ a, Complex^ x, Int its) gave all sorts of errors.  Like
Error      1      error C3699: '^' : cannot use this indirection on type 'VecComplex_I'
Error      2      error C3699: '^' : cannot use this indirection on type 'Complex'      
Error      3      error C2228: left of '.size' must have class/struct/union
Error      4      error C2679: binary '=' : no operator found which takes a right-hand operand of type 'VecComplex_I' (or there is no acceptable conversion)      
Error      5      error C2665: 'std::abs' : none of the 6 overloads could convert all the argument types      
Error      6      error C2678: binary '*' : no operator found which takes a left-hand operand of type 'Complex *' (or there is no acceptable conversion)      
Error      7      error C2678: binary '*' : no operator found which takes a left-hand operand of type 'Complex *' (or there is no acceptable conversion)      
Error      8      error C2678: binary '*' : no operator found which takes a left-hand operand of type 'Complex *' (or there is no acceptable conversion)      
Error      9      error C2679: binary '-' : no operator found which takes a right-hand operand of type 'Complex' (or there is no acceptable conversion)      
Error      10      error C2679: binary '==' : no operator found which takes a right-hand operand of type 'Complex' (or there is no acceptable conversion)      
Error      11      error C2440: '=' : cannot convert from 'Complex' to 'Complex *'      
Error      12      error C2677: binary '-=' : no global operator found which takes type 'std::complex<double>' (or there is no acceptable conversion)      
Error      13      error C2664: 'Numerical_Methods::Roots::laguer' : cannot convert parameter 1 from 'VecComplex' to 'VecComplex_I *'      
Error      14      error C2664: 'Numerical_Methods::Roots::laguer' : cannot convert parameter 1 from 'VecComplex_I' to 'VecComplex_I *'      


// Numerical_Methods.h
 
#pragma once
#include "nr3.h"
 
using namespace System;
 
namespace Numerical_Methods 
{
 
	public ref class Roots
	{
		public: 
			
			static void laguer(VecComplex_I^ a, Complex^ x, Int &its)
		{
			const Int MR=8, MT=10, MAXIT =MT*MR;
			const Doub EPS=numeric_limits<Doub>::epsilon();
 
			static const Doub frac[MR+1]=
			{0.0,0.5,0.25,0.75,0.13,0.38,0.62,0.88,1.0};
 
			Complex dx,x1,b,d,f,g,h,sq,gp,gm,g2;
			Int m=a.size()-1;
			for (Int iter = 1; iter<=MAXIT; iter++)
			{
				its = iter;
				b=a[m];
				Doub err=abs(b);
				d=f=0.0;
				Doub abx =abs(x);
				for (Int j=m-1;j>=0;j--)
				{
					f=x*f*d;
					d=x*d+b;
					b=x*b+a[j];
					err=abs(b)+abx*err;
				}
				err *=EPS;
				if(abs(b)<=err) return;
				g=d/b;
				g2=g*g;
				h=g2-2.0*f/b;
				sq = sqrt(Doub(m-1)*(Doub(m)*h-g2));
				gp=g+sq;
				gm=g-sq;
				Doub abp =abs(gp);
				Doub abm = abs(gm);
				if(abp<abm) gp=gm;
				dx=MAX(abp,abm)>0 ? Doub(m)/gp : polar(1+abx,Doub(iter));
				x1=x-dx;
				if(x==x1) return;
				if (iter % MT != 0) x=x1;
				else x -= frac[iter/MT]*dx;
			}
			throw("too many iterations in laguer");
 
		}
 
 
 
	
			static void zroots(VecComplex_I a, VecComplex_O roots, const Bool polish)
		{
			const Doub EPS=1.0e14;
			Int i, its;
			Complex x,b,c;
			Int m=a.size()-1;
			VecComplex ad(m+1);
			for (Int j=0;j<=m; j++) ad[j]=a[j];
			for (Int j=m-1;j>=0;j--)
			{
				x=0.0;
				VecComplex ad_v(j+2);
				for(Int jj=0;jj<j+2;jj++) ad_v[jj]=ad[jj];
				laguer(ad_v,x,its);
				if(abs(imag(x)) <= 2.0*EPS*abs(real(x)))
					x=Complex(real(x),0.0);
				roots[j]=x;
				b=ad[j+1];
				for (Int jj=j;jj>=0;jj--)
				{
					c=ad[jj];
					ad[jj]=b;
					b=x*b+c;
				}
			}
			if(polish)
				for (Int j=0;j<m;j++)
					laguer(a,roots[j],its);
			for(Int j=1;j<m;j++)
			{
				x=roots[j];
				for (i=j-1; i>=0;i--)
				{
					if (real(roots[i])<=real(x)) break;
					roots[i+1]=roots[i];
				}
				roots[i+1]=x;
			}
		}
 
 
	};
}

Open in new window

0
 

Author Comment

by:perrytaylor
ID: 24240954
Ok, we might be getting somewhere.  The following code does appear in my C# app.

                  static void test(double in)
                  {
                        double tets = in;
                  }

What could it be about the header file/ custom variables that it doesn't like?
0
 
LVL 19

Expert Comment

by:alb66
ID: 24240973
I think that VecComplex_I is not a .net compliant type. You should write a wrapper (.net class) for it
0
 

Author Comment

by:perrytaylor
ID: 24249702
How would I go about writing a wrapper class?
0
 
LVL 19

Accepted Solution

by:
alb66 earned 2000 total points
ID: 24249873
The following article is a good starting point (it use .net c++ old syntax!):

"Writing Managed Wrappers with Managed C++" at
http://www.ondotnet.com/pub/a/dotnet/2004/03/29/mcpp_part3.html
0
 
LVL 9

Expert Comment

by:tculler
ID: 24275951
Just a quick comment, C++ uses a concept called "name-mangling", where it basically "mangles" the hell out of your function names to enable function overloading. In other words, it appends some extra junk on the end of each function's identifier in order to diferentiate them by more than just their name. I believe Managed C++ prevents this, but I may be wrong.

I can't explain every little thing that may be going wrong here, but on top of the name-mangling, your probably may lie in the CLS (Common Language Specification), and whether or not these objects you're handling in C++ are CLS-Compliant. The reason these objects must be "compliant" is because every native C++ type you use in C# must be "mapped out" to a corresponding type in C# (for example, Native C++'s "char" primitive type maps out the a "System.SByte" in VC#).

A third problem may arise from VC# being so strict about having some sort of a passion for hating pointers. Any code block that utilizes pointers in VC# MUST appear within an "unsafe" block, as well as the entire assembly be compiled with the /unsafe switch. This essentially overrides some of the .NET Framework's type-safety checking, allowing for pointers, the useage of the stackalloc keyword, among other things.
0
 

Author Closing Comment

by:perrytaylor
ID: 31574890
I apologize for the long delay.  I decided to go a different route but this is certainly the answer to my question.
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

Question has a verified solution.

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

Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses

872 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