I am new to .net .
I have a managed C++ library. It looks like this.
// header file
namespace cppnetdll
{
public __gc class Class1
{
public:
static int foo_int(void);
};
}
// source file
namespace cppnetdll
{
int Class1::foo_int(void)
{
return 123;
}
}
I can call this from a managed c++ program. When I try to call it from
a C# program, I get the compiler error: "The type or namespace name
'Class1' could not be found (are you missing a using directive or an
assembly reference?)" The error refers to the DllImport line below.
Here is the C# code
[code:1:a72c1df571]
namespace csuser
{
public class xxx
{
[DllImport("cppnetdll.dll")] extern
int Class1.foo_int();
private void yyy() { int i =
foo_int(); }
}
}[/code:1:a72c1df571]
I have tried various approaches but no success. What is the magic
syntax ?
It's funny that I can call unmanaged C++ functions from C# fairly
easily by declaring the functions as "C" and exporting from the DLL.
I expected calling managed code to be easier. Maybe it's so easy
that no one thought of documenting it !
You do not use a [DllImport] directive to call code that's written in managed C++. That is only intended for native DLLs that export their functions. Neither of which applies to yours, it isn't native and you don't export the function.
You built a managed assembly, you can treat it just like one you'd have written in C#. Project + Add Reference, Browse tab, navigate to the DLL. Or better yet, put both projects in one solution, use the Projects tab to select the reference.
Instead of using the [DllImport ...]
Try just adding a reference, here is a how to from MSDN:
http://msdn.microsoft.com/en-us/library/7314433t%28v=VS.90%29.aspx
Related
So I have a WPF solution. I added a new project and added a CPP Dll project to it.
I used this example. Pretty straight forward.
http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w
Here is my code
CppTestDll.cpp
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL()
{
printf("Hello from DLL !\n");
}
}
When I build this I do in fact get a DLL
Now when I go into my WPF app and attempt to add a reference to this DLL I get this error.
"A reference to 'C:\DIR\testcppdll.dll' could not be added. Please
make sure that the file is accessible, and that it is a valid assembly
or COM component."
If you look in the example you cite:
Creating a simple C# application:
Start Visual Studio .NET. Go to File->New->Project.
Select Visual C#
Project. ... (you can select WPF Project)
Give the name to your application. Press OK. Into the specified
class, insert the following two lines:
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL ();
In C#, keyword extern indicates that the method is implemented externally.
Your code should look something like this:
using System;
using System.Runtime.InteropServices; // DLL support
class HelloWorld
{
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL ();
public void SomeFunction()
{
Console.WriteLine ("This is C# program");
DisplayHelloFromDLL ();
}
}
You don't add a reference to the to the DLL - you P/Invoke the Function using DLLImport
I've been requested to create a .Net dll for an old delphi program. I'm trying to do this with a COM Callable Wrapper, but I keep getting an error when it tries to load the dll (pretty general, something like "I couldn't load the dll"). Here is what the technical documentation says:
The DLL only needs to export one function under the name 'AUTHORIZE'.
function Authorize(InXml: PChar): PChar; stdcall;
(Delphi syntax. May be different in other languages.)
Here is my code for the CCW:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ComCallableWrapper
{
[Guid("C3FD922A-FB44-47B1-9C0C-8F7FAF57098B")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IAuthorizer
{
[DispId(1)]
string Authorize(string lnpInXml);
}
[ProgId("ComCallableWrapper.Authorizer")]
[ClassInterface(ClassInterfaceType.None)]
public class Authorizer : IAuthorizer
{
public Authorizer()
{
}
public string Authorize(string lnpInXml)
{
return "Approved!";
}
}
}
I also run this command "regasm /tlb:ComCallableWrapper.tlb ComCallableWrapper.dll /codebase" on the computer where the delphi program is running.
I've been doing some research on google about how delphi invokes functions on a dll, and I found at least 2 ways:
function Authorize(lnpInXml: pchar): pchar; stdcall; external 'DLLName.dll';
and
oleObject := CreateOleObject('ComCallableWrapper.Authorizer');
ShowMessage(oleObject.Authorize('Approved?'));
It looks like COM works a little bit different. Is there a way to change my CCW to work like the first way?
Regards.
You con't need COM. And indeed using COM is a mistake because the Delphi program is not looking for a COM DLL.
What you need to do is to export an unmanaged function from your managed C# DLL. That's a little tricky and is in fact not supported. These are your most attractive options:
Use Robert Giesecke's UnmanagedExports.
Write a mixed mode C++/CLI DLL that consumes your C# code. The mixed mode C++/CLI is capable of export native functions using __declspec(dllexport), .def files etc.
If you chose to use UnmanagedExports, the function would look like this:
[DllExport]
public static IntPtr Authorize(string InXml)
{
// your code goes here, for now return the input value
return Marshal.StringToHGlobalAnsi(InXml);
}
Implementing the function is a little tricky because you need to return a Delphi PAnsiChar, that is a C++ char*. You cannot use string for the return type and have to use IntPtr. But how do you allocate the string so that it remains valid for the caller to use it. The code above leaks the string in an HGLOBAL.
I can't advise you definitively how to resolve the lifetime of the string. The interface you are coding to is not at all well designed. Only you with more knowledge of the interface are in a position to resolve that issue.
Below is my code in c#...
here callback is too implemented in c# only.
i want a callback from c++ dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
class Program
{
// [DllImport("C:/Users/kool/Documents/Visual Studio 2010/Projects/DLL/Debug/DLL.dll", CallingConvention = CallingConvention.Cdecl)]
static void Main(string[] args)
{
function1(function2); // i want thia function2 to be fetched from ++ dll
}
public delegate void fPointer(); // point to every functions that it has void as return value and with no input parameter
public static void function1(fPointer ftr)
{
fPointer point = new fPointer(ftr);
point();
}
public static void function2()
{
Console.WriteLine("Bla");
}
}
i will createa a dLL from where i will send function2 to
function1(function2);
how can i implement it??
One way is exporting the C# assembly as a type library and using it from C++ as if it were a COM component.
Use TlbExp.exe in the Visual Studio command prompt to export the C# assembly as a type library. Then register the type library with RegAsm.exe. Then in the C++ code use the #import directive to import the type library. You can now use the C# classes from C++ as if they were COM classes.
For more detail see: http://msdn.microsoft.com/en-us/library/ms172270.aspx
Edit: Sorry, which is it that you want to do: use C++ from C#, or use C# from C++?
Either one is possible. The link above explains how to use C# from C++. This one explains how to use C++ from C#: http://msdn.microsoft.com/en-us/library/z6tx9dw3.aspx
You can send pointer to your managed .net function and call it from unmamaged code (callback).
Detail here http://habrahabr.ru/post/130690/ (use google to translate it from russian if needed, but you need to look at last two code example).
Also check your code calling - it should comply on both managed and unmanaged sides (use __stdcall in C-code and CallingConvention = CallingConvention.Cdecl in DllImport attribute).
I´m unexperienced with handling DllImport stuff, so I´d be glad if anyone of you can solve my little problem. I want to import a dll which has a method within a class. The method should return a stringarray.
So here´s some code:
Form1.cs (Calling Position):
...
public partial class Form1 : Form
{
[DllImport("lang.dll")]
public static extern string[] getValues();
// |
//error occures here v
string[] labels = getValues();
Status prgmStatus;
public Form1()
{
...
language.cs (Class of my .dll file):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace lang
{
public class language
{
public language()
{
}
public string[] getValues()
{
string[] content =
{
"User",
"Password",
"Login",
"Create new account ->",
"Repeat password",
"E-Mail adress",
"Register",
"<- Back to Login"
};
return content;
}
}
}
So when I start my program it calls the method of the dll and this appears:
(Image is found here:
How may i avoid this error and get the array properly?
Thanks for answers and solutions,
Paedow
Update:
It should be possible to load any other .dll file from this path, with same structure but other content. The dll contains the labels for the windows form in the english language. when someone wants to have this program in his own language he has to compile a dll with his labels and just replace the dll.
Another Update:
The dll file is not build in the same solution. The dll is an own solution, only the final .dll file will be used in my program, so there are no references.
As you are working with managed dlls, you shouldn't use the [DllImport], which should be used only with unmanaged dlls (see here the distinction).
from now on, every time I mention a "dll" I mean a "managed dll"
If you want to compile your application with the dll (instead of loading it "manually" during execution, which I guess you don't want...) you can add a reference to:
The compiled dll file (".NET Reference");
The .dll project ("Project Reference"), only if the .dll project and the .exe project are in the same solution.
See here the official documentation on this. For more on solutions/projects you can start here.
You don't have to DllImport managed assembly as #Simon Whitehead said. Just reference it in your project and then
var l = new lang.language();
string[] labels = l.getValues();
Greetings,
I am sorry for bothering, I'll show the question:
I am trying to export some functions written in c++ in a DLL in order to import them in a C# Application running on Visual Studio.
I make the export as reported in the following code,
tobeexported.h:
namespace SOMENAMESPACE
{
class __declspec(dllexport) SOMECLASS
{
public:
SOMETYPE func(param A,char b[tot]);
};
}
tobeexported.cpp:
#include "stdafx.h"
#include "tobeexported.h"
...
using namespace SOMENAMESPACE;
SOMETYPE SOMECLASS:: func(param A,char b[tot])
{
...some stuff inside...
}
The dll is righly created and the code is already CLR-managed(looked with a disassembling software(reflector)) and contains the exported functions
then I "Add the Reference" in my c# application and the dll is found, but when
I open it with the object browser it is completely empty, neither class, nor object has been exported and ready to be used
can you help me please?
thanks
best regards
What about using managed C++ to compile your DLL? Then you just have to add a ref to the class like this:
namespace SOMENAMESPACE
{
public ref class SOMECLASS
{
public:
SOMETYPE func(param A,char b[tot]);
};
}
After successful compilation and referencing in the other project, the class should be visible. Exporting native C++ is not really portable, each compiler produces different results and is tedious to bind from within C#...
EDIT: added public access modifier to ref class...