How Call the function from .dll using c# program - c#

I tried to call the function from .dll file using java native interface ,its successfully working, But I don't know how to call function from .dll using C# ,please advice me on this.

Look at DLLImport attribute in MSDN
http://msdn.microsoft.com/en-us/library/aa664436(v=vs.71).aspx
using System;
using System.Runtime.InteropServices;
class Example
{
[DllImport("your_dll_here.dll")]
static extern int SomeFuncion1(int parm);
static void Main()
{
int result = SomeFunction1(10);
}
}

If it's a native DLL, you need to add a DLLImport statement, importing the function you want.
The documentation is here.
The attribute looks like this, typically:
[DllImport("YourDllNameHere.dll")]
public static extern int YourFunction(int input);
This will import a function called YourFunction (which takes an int input, and returns an int) from YourDllNameHere.dll.

Let's say your DLL name is MyLibrary and MyFunction is the function contain in your DLL .
First right click on your Reference , browse and add your DLL .
Declare your DLL as a namespace using MyLibrary;
And you can call MyFunction !
Or
Another way ,
you can use this msdn reference !

Add that dll into your project as a referenced dll into reference folder(right click on references ,add reference then "Browse" to you DLL).then it should be available for to use as you want and just use that dll as follows in the code level.
using System;
using YourDllName;
class ExampleClass
{
//you can use your dll functions
}

I like the link provided by Baldrick for DllImport attribute.
This is what I recommend.
Download Dependency Walker (small application exe, no need to install).
Open your DLL in the Dependecy Walker to view the exposed entry points of DLL.
Declare external call to native function in C# like this.
C#:
[DllImport("Your_DLL.DLL", EntryPoint="Function_Entry_Point",CallingConvention=CallingConvention.StdCall)]
static extern IntPtr Function1();
Note:
If entry point is not specified the function name is considered as the entry point.
When you run the application make sure the native DLL is in the
same folder.

Related

Sharing function between c and c# [duplicate]

I have a C lib and want to call function in this library from C# application. I tried creating a C++/CLI wrapper on the C lib by adding the C lib file as linker input and adding the source files as additional dependencies.
Is there any better way to achieve this as am not sure how to add C output to c# application.
My C Code -
__declspec(dllexport) unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen);
My CPP Wrapper -
long MyClass::ConnectSessionWrapper(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen)
{
return ConnectSession(handle, publicKey, publicKeyLen);
}
The example will be, for Linux:
1) Create a C file, libtest.c with this content:
#include <stdio.h>
void print(const char *message)
{
printf("%s\\n", message);
}
That’s a simple pseudo-wrapper for printf. But represents any C function in the library you want to call. If you have a C++ function don’t forget to put extern C to avoid mangling the name.
2) create the C# file
using System;
using System.Runtime.InteropServices;
public class Tester
{
[DllImport("libtest.so", EntryPoint="print")]
static extern void print(string message);
public static void Main(string[] args)
{
print("Hello World C# => C++");
}
}
3) Unless you have the library libtest.so in a standard library path like “/usr/lib”, you are likely to see a System.DllNotFoundException, to fix this you can move your libtest.so to /usr/lib, or better yet, just add your CWD to the library path: export LD_LIBRARY_PATH=pwd
credits from here
EDIT
For Windows, it's not much different.
Taking an example from here, you only have yo enclose in your *.cpp file your method with extern "C"
Something like
extern "C"
{
//Note: must use __declspec(dllexport) to make (export) methods as 'public'
__declspec(dllexport) void DoSomethingInC(unsigned short int ExampleParam, unsigned char AnotherExampleParam)
{
printf("You called method DoSomethingInC(), You passed in %d and %c\n\r", ExampleParam, AnotherExampleParam);
}
}//End 'extern "C"' to prevent name mangling
then, compile, and in your C# file do
[DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")]
public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam);
and then just use it:
using System;
using System.Runtime.InteropServices;
public class Tester
{
[DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")]
public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam);
public static void Main(string[] args)
{
ushort var1 = 2;
char var2 = '';
DoSomethingInC(var1, var2);
}
}
UPDATE - Feb 22 2019: Since this answer has been getting quite a few upvotes, I decided to update it with a better way of calling the C method. Previously I had suggested using unsafe code, but the safe and correct way is to use MarshalAs attribute for converting a .NET string to a char*. Also, in VS2017 there is no Win32 project anymore, you'll probably have to create a Visual C++ dll or empty project and modify that. Thank you!
You can directly call C functions from C# by using P/Invoke.
Here's a short how-to on creating a C# lbrary that wraps around a C dll.
Create a new C# Library project (I'll call it "Wrapper")
Add a Win32 project to the solution, set application type to: DLL (I'll call it "CLibrary")
You can remove all the other cpp/h files since we won't need them
Rename the CLibrary.cpp file to CLibrary.c
Add a CLibrary.h header file
Now we need to configure the CLibrary project, right-click it and go to properties, and select Configuration: "All Configurations"
In Configuration Properties > C/C++ > Precompiled headers, set Precompiled Headers to: "Not using Precompiled Headers"
In the same C/C++ branch, go to Advanced, change Compile As to: "Compile as C code (/TC)"
Now in the Linker branch, go to General, and change Output File to: "$(SolutionDir)Wrapper\$(ProjectName).dll", this will copy the built C DLL to the C# project root.
CLibrary.h
__declspec(dllexport) unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen);
CLibrary.c
#include "CLibrary.h"
unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen)
{
return 42;
}
Right-click CLibrary project, build it, so we get the DLL in the C# project directory
Right-click C# Wrapper project, add existing item, add CLibrary.dll
Click on CLibrary.dll, go to the properties pane, set "Copy to output Directory" to "Copy Always"
It's a good idea to make the Wrapper project dependent on CLibrary so CLibrary gets built first, you can do that by right-clicking the Wrapper project, going to "Project Dependencies" and checking "CLibrary".
Now for the actual wrapper code:
ConnectSessionWrapper.cs
using System.Runtime.InteropServices;
namespace Wrapper
{
public class ConnectSessionWrapper
{
[DllImport("CLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
static extern uint ConnectSession(uint handle,
[MarshalAs(UnmanagedType.LPStr)] string publicKey,
char publicKeyLen);
public uint GetConnectSession(uint handle,
string publicKey,
char publicKeyLen)
{
return ConnectSession(handle, publicKey, publicKeyLen);
}
}
}
Now just call GetConnectSession, and it should return 42.
Result:
Okay well, Open VS 2010, Goto File -> New -> Project -> Visual C++ -> Win32 -> Win32 Project and give it a name (HelloWorldDll in my case), Then in the window that follows under Application Type choose 'DLL' and under Additonal Options choose 'Empty Project'.
Now goto your Solution Explorer tab usually right hand side of VS window, right click Source Files -> Add Item -> C++ file (.cpp) and give it a name (HelloWorld in my case)
Then in the new class paste this code:
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL()
{
printf ("Hello from DLL !\n");
}
}
Now Build the project, after navigate to your projects DEBUG folder and there you should find: HelloWorldDll.dll.
Now, lets create our C# app which will access the dll, Goto File -> New -> Project -> Visual C# -> Console Application and give it a name (CallDllCSharp), now copy and paste this code to your main:
using System;
using System.Runtime.InteropServices;
...
static void Main(string[] args)
{
Console.WriteLine("This is C# program");
DisplayHelloFromDLL();
Console.ReadKey();
}
and build the program, now that we have both our apps built lets use them, get your *.dll and your .exe (bin/debug/.exe) in the same directory, and execute the application output should be
This is C# program
Hello from DLL !
Hope that clears some of your issues up.
References:
How to create a DLL library in C and then use it with C#
NOTE : BELOW CODE IS FOR MULTIPLE METHODS FROM DLL.
[DllImport("MyLibc.so")] public static extern bool MyLib_GetName();
[DllImport("MyLibc.so")] public static extern bool MyLib_SetName(string name);
[DllImport("MyLibc.so")] public static extern bool MyLib_DisplayName(string name);
public static void Main(string[] args)
{
string name = MyLib_GetName();
MyLib_SetName(name);
MyLib_DisplayName(name);
}
The P/Invoke method has been described extensively and repeatedly, ok so far.
What I'm missing here is, that the C++/CLI method has a big advantage: Calling safety.
In contrast to P/Invoke, where the call of the C funtion is like shooting blind into the sky (if this comparison is allowed), nobody will check the function arguments when calling the C function.
Using C++/CLI in this case means normally, you include a headerfile with the functions prototypes you want to use. If you are calling the C function with wrong/to much /to few arguments, the compiler will tell you.
I don't think you can say in general which is the better method, honestly I don't like either of them.

Java JNI call to C# COM fails, when COM is registered without codebase option of regasm

Function calls from Java to C# through JNI-C++/CLI are failing when the C# COM is not registered using regasm with the codebase option. I've built a sample following the instructions in P2: Calling C# from Java with some changes.
Numero uno: C#
Change the C# dll into a COM by creating an interface, IRunner, and making the library assembly COM-visible.
namespace RunnerCOM
{
public interface IRunner
{
String ping();
}
public class Runner:IRunner
{
static void Main(string[] args)
{
}
public Runner() { }
public String ping()
{
return "Alive (C#)";
}
}
}
Numero due: Java
No changes made to the Java section.
Numero tre: C++
This part was changed to create a new instance of the RunnerCOM.Runner class and use that result. Here is a good tutorial on how to call managed code from unmanaged code: http://support.microsoft.com/kb/828736
#include "stdafx.h"
#include "Runner.h"
#pragma once
#using <mscorlib.dll>
#import "RunnerCOM.tlb"
JNIEXPORT jstring JNICALL Java_Runner_ping(JNIEnv *env, jobject obj){
RunnerCOM::IRunnerPtr t = RunnerCOM::IRunnerPtr("RunnerCOM.Runner");
BSTR ping = t->ping();
_bstr_t temp(ping, true);
char cap[128];
for(unsigned int i=0;i<temp.length();i++){
cap[i] = (char)ping[i];
}
return env->NewStringUTF(cap);
}
Now to my questions,
The code above fails with a _com_error exception, Class not registered (0x80040154) unless the codebase option is enabled during regsitration of RunnerCOM.dll, with regasm.exe. Why is this? If the code is not ran from JNI, I tested it as an exe, it works fine. The RunnerCOM.dll is simply found in the working directory.
Type casting _bstr_t temp to char* fails. For example, char *out = (char*) temp; Similar to the issue above, it works fine when it's built and executed as an exe but crashes the JVM when it's a JNI call.
By the way this is what I used to run it as an executable:
int main(){
RunnerCOM::IRunnerPtr t = RunnerCOM::IRunnerPtr("RunnerCOM.Runner");
BSTR ping = t->ping();
_bstr_t temp(ping, false);
printf(temp);
return 0;
}
Codebase creates a Codebase entry in the registry. The Codebase entry specifies the file path for an assembly that is not installed in the global assembly cache, so when you specify the codebase, the system will find the DLL based on the path. If not, it will try to locate the dll in the GAC and current working directory. In JNI, I think the current working directory is not the folder where the DLL is. You can use process explorer to find what is the current working directory, also, you can use process monitor to find out which directories the exe is looking into to find the dll.
The code converting _bstr_t to char*, the char* string cap is not ended with '\0', I think this might cause problem in JNI. Uses the _bstr_t operator (char *), you can obtain a null terminated string from the _bstr_t object. Please check the msdn example for details.
You mentioned C++/CLI, C++/Cli and COM warpper are two different ways to interop with C# code. If you're using C++/CLI as a bridge, you doesn't need to register C# DLL as COM, please see this: Calling .Net Dlls from Java code without using regasm.
If you're using COM, you should call CoInitialize() to init COM first in your code.

How to use dll created using C# in Visual C++?

Here are the steps what I have done.
I have created a .dll file using C# with the content as
public static int MyFunction(int dummy)
{
MessageBox.Show("I am in dll");
return 0;
}
I have also created an MFC application (exe) with content as
int main()
{
int a = MyFunction(0);
return 0;
}
Is this right way to do the call ?
Note:
i. I have changed my MFC application to /cl (common language run time support)
ii. I have also added C# file in the MFC's Reference.
Problems I faced:
Error 1 error C3861: 'MyFunction': identifier not found
Warning 2 warning C4793: 'MyDialog::`vcall'{132}'' : function compiled as native :
I have used the following command in the MyDialog.cpp file as a last line, the warning is solved.
#pragma unmanaged
Now how to solve the Error?
The C# code is placed inside a class, say MyClass. If you want to call a static member of this class in C++/CLI, you need to use MyClass::MyFunction(0).
Finally, you would need to add the namespace: MyNamespace::MyClass::MyFunction(0).
You can compile your C++ program with the /clr flag and use C++/CLI to simply call any .NET code (as long as you include a reference to it).
You could also use a COM callable wrapper for your C# code (compiled in a DLL) -> check this article

Call native method from dll

I am trying to use MimeTex.dll in Mixed Mode of C++/CLI project. I include the dll by:
#pragma comment(lib,"MimeTex.dll")
and I tried to call this method:
CreateGifFromEq("expression","path");
but the compiler inform that it doesn't know CreateGifFromEq() method.
I didn't find resources in the web in how to use MimeTex.dll in C++. I just find how to use it with C# in this link by Pinvok like:
[System.Security.SuppressUnmanagedCodeSecurity()]
internal class NativeMethods
{
private NativeMethods()
{ //all methods in this class would be static
}
[System.Runtime.InteropServices.DllImport("MimeTex.dll")]
internal static extern int CreateGifFromEq(string expr, string fileName);
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
internal extern static IntPtr GetModuleHandle(string lpModuleName);
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
internal extern static bool FreeLibrary(IntPtr hLibModule);
}
and then call it like:
NativeMethods.CreateGifFromEq(equation, tempGifFilePath);
How I can call it without Pinvok in mixed mode of C++/CLI?
Surely you meant to write:
#pragma comment(lib,"MimeTex.lib")
In other words, you pass the .lib file to the linker rather than the .dll. When you compiled the DLL, a .lib file will have been generated.
But that's not your immediate problem. The compiler has no declaration for CreateGifFromEq. That's because you have not included the library's header file in your C++ code. Doing that should resolve the issue.
If all you need is that one function then it should be trivial to declare it in your C++ code.
__declspec(dllimport) extern int CreateGifFromEq(char *expr, char *fileName);
You probably will need to wrap that in an extern "C" block too.
Actually, having looked at the library, the header file that is supplied with the source does not declare that function, even though it's present in the library.
In C++/CLI you can use P/Invoke as in C#.
If you don't want to use P/Invoke, the other way is to load the DLL with LoadLibrary and get pointers to the functions with GetProcAddress.
Here's the equivalent of the C# code in C++/CLI:
using namespace System;
using namespace System::Runtime::InteropServices;
private ref class NativeMethods abstract sealed
{
internal:
[DllImport("MimeTex.dll")]
static int CreateGifFromEq(String^ expr, String^ fileName);
[DllImport("kernel32.dll")]
static IntPtr GetModuleHandle(String^ lpModuleName);
[DllImport("kernel32.dll")]
[returnvalue: MarshalAs(UnmanagedType::Bool)]
static bool FreeLibrary(IntPtr hLibModule);
};
As you can see it's almost identical to the C# code except for some minor syntax changes.
Here's how you would use LoadLibrary and GetProcAddress (which has the advantage of not requiring marshaling, which is unnecessary in C++ anyway):
HMODULE hModule = LoadLibrary(L"MimeTex.dll");
int (*fpCreateGifFromEq)(WCHAR*, WCHAR*) = GetProcAddress(hModule, "CreateGifFromEq");
(*fpCreateGifFromEq)(L"expression", L"filename");
You don't need to do that for GetModuleHandle and FreeLibrary, because they're from kernel32.dll so you can just include Windows.h and call them normally.
There's a cleaner way of doing things:
Create a C++/CLI project. It will be your interface between C# and C++ (this is what C++/CLI is aimed at).
Make your C# project have a reference to this new assembly.
Inside your new C++/CLI project, configure project options so as you point to the directory with mimetex .h files for the compiler to compile your project, and the directory with .lib/.dll for the linker.
Inside your C++/CLI part, you just write C++ inside the functions. They are exposed to your C# assembly, but in the inside it's just calls to C++ functions as usual.
(You should check a C++CLI tutorial to know what to do with strings to convert them to native char or std::string. I remember I had to look at that.)*
In your C# part, you just call the C++CLI project assembly exposed functions like normal C# functions, without noticing it's native code called behind.

Using a managed c# dll inside an unmanaged c++ dll

How does an unmanaged c++ .dll know where the location of a managed c# .dll is?
Some context:
I have a c++ .dll that imports a type library (.tlb) and inside one of the c++ functions, I instantiate a pointer to the functions inside the c# .dll. Then, using that pointer, I can call the c# functions in c++. I would like to know how c++ .dll know where the c# .dll is? Further, is there a better way to do this type of coding?
Does the .tlb need to be in the same directory as the c# .dll?
One way to accomplishing the above is to register the C# dll file with the Microsoft Windows Registry using the regasm command. This command EXE is included with distributions of Visual Studios. An example use of the command follows:
regasm NameofC#DLL.dll /tlb:NameofC#DLL.tlb
Once you have registered it in the registry you will need to install it to the global assembly cache (GAC) using the gacutil command. This is also included with distributions of Visual Studios. An example use of the command follows:
gacutil /i NameofC#DLL.dll
Once these steps are completed your C++ code will be able to find the C# dll assuming your DLL files are constructed similar to the following:
[C#]
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace MyNameSpace
{
/// <summary>
/// Interface for C++ DLL. This exposes the functions used inside the dll
/// Make sure the return types, function names, and argument types match the class
/// </summary>
[ComVisible(true)]
[Guid("CBA208F2-E43B-4958-97C7-C24EA5A213DE")]
public interface IMyClass
{
int Function1();
int Function2();
}
[ClassInterface(ClassInterfaceType.None)]
[Guid("579091E6-83A1-4aa5-89A7-F432AB2A57E3")]
[ComVisible(true)]
public class MyClass : IMyClass
{
public MyClass()
{
//Constructor
}
public int Function1()
{
//Do something in C#
return an integer;
}
public int Function2()
{
//Do something else in C#
return an integer;
}
}//End Class MyClass
}//End namespace MyNameSpace
Everywhere you see a GUID being used, that is a randomly generated global identifier used to identify your C# code. This number can be randomly generated using the GUID creation tool provided with Visual Studios under the "Tool menu" and the "Create GUID" option. Select Registry format and press "New GUID". Then just press copy and paste it where the GUID needs to be (Remove the brackets!)
[C++]
#include <windows.h>
#include "stdafx.h"
#include <cstdlib>
#pragma warning (disable: 4278)
#import <mscorlib.tlb> raw_interfaces_only
#include <stdio.h>
//This path needs to be valid at compile time. The file does not need to be there in runtime when using the DLL after compile.
#import "C:\\...\\NameofC#DLL.tlb" no_namespace named_guids
extern "C" _declspec(dllexport) int _Function1()
{
int result = 0;
IMyClass *CSharpInterface = NULL;
//Open interface to C#
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_MyClass, NULL, CLSCTX_INPROC_SERVER,
IID_IMyClass, reinterpret_cast<void**>(&CSharpInterface));
//Call Function1 C# method
result = CSharpInterface->Function1();
//Close interface
CoUninitialize();
//Return result
return result;
}
The required TLB file at compile time can be generated using the tlbexp command also included with visual studios.An example use of the command follows:
tlbexp NameofC#DLL.dll
If you do not specify a path it will default to the following path:
C:\Program Files\Microsoft Visual Studio 9.0\VC
There a several places you can mess this up and the C# DLL call will fail.
Regards,
SeaMossDesign
Maybe I'm missing something, but you can create a custom CLR host and invoke a method from C# without pointer. Check ICLRRuntimeHost::ExecuteInDefaultAppDomain out.

Categories

Resources