Access a function present in C# dll using Python - c#

I want to access a function my_function() present in a c# file which is compiled into a .net dll - abc.dll.
C# file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
public class Class1
{
public string my_function()
{
return "Hello World.. :-";
}
}
}
After compiling the above code to abc.dll
Using the below python trying to access my_function()
import ctypes
lib = ctypes.WinDLL('abc.dll')
print lib.my_function()
Above code throws error
lib.my_function()
Traceback (most recent call last):
File "", line 1, in
File "C:\Anaconda\lib\ctypes__init__.py", line 378, in getattr
func = self.getitem(name)
File "C:\Anaconda\lib\ctypes__init__.py", line 383, in getitem
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'my_function' not found

You haven't made the function visible in the DLL.
There are a few different ways you can do this. The easiest is probably to use the unmanagedexports package. It allows you to call C# functions directly like normal C functions by decorating your function with [DllExport] attribute, like P/Invoke's DllImport. It uses part of the subsystem meant to make C++/CLI mixed managed libraries work.
C# code
class Example
{
[DllExport("ExampleFunction", CallingConvention = CallingConvention.StdCall)]
public static int ExampleFunction(int a, int b)
{
return a + b;
}
}
Python
import ctypes
lib = ctypes.WinDLL('example.dll')
print lib.ExampleFunction(12, 34)

Related

how to get dependency of my C# dll in ctypes library python?

I want to run C# dll with .net framework 4.7 in python app.
I use dllExport nuget for my method in dll because ctypes with this way access my method.
Sample:
using System.Runtime.InteropServices;
namespace MyNameSpace
{
public class MyClass
{
[DllExport("MyMethod", CallingConvention = CallingConvention.StdCall)]
public static int MyMethod(int a,int b)
{
return a + b;
}
}
}
In python:
def myFunction():
Dllpath = os.path.join("dll folder directory")
os.add_dll_directory(Dllpath + r"myDll.dll")
# WinDll used just windows os, in Linux is different
lib = WinDLL(Dllpath + r"myDll.dll")
lib.MyMethod(12,17)
it is work.
but when I use other library (dll) in my dll I get this Error:
[WinError -532462766] Windows Error 0xe0434352
I guess this error was for problem in dependency of my dll.
how to resolve this error?
you should put "DllExport" above all functions you call in all dependencies too.

vsnprintf and snprintf causing dll to not load

I've been fighting this for days. I have a Visual Studio .net project written in C# that needs to load a dll written in C using gcc compilers on the Codeblocks IDE.
The dll can be loaded and used fine, but when I use vsnprintf in the dll, the .net project says "Unable to load DLL. The specified module could not be found." whenever I try to call a function from the dll.
Relevant C# code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace Scratchpad
{
public partial class frmMain : Form
{
[DllImport("testpielibs", CallingConvention = CallingConvention.Cdecl)]
static extern void SomeFunction(string a);
private void button3_Click(object sender, EventArgs e)
{
SomeFunction("ABC");
}
}
}
Relevant C (the DLL) code:
#include <stdio.h>
#include <stdarg.h>
#define DLL_EXPORT __declspec(dllexport)
void DLL_EXPORT SomeFunction(const LPCSTR sometext)
{
MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);
}
DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
int log_printf(char *format, ...)
{
char msg[256];
va_list ap;
memset(msg, 0, sizeof msg);
va_start(ap, format);
vsnprintf(msg, 256, format, ap);
va_end(ap);
return 0;
}
Notice that "SomeFunction" doesn't even call "log_printf". The project builds fine regardless, and when I comment out the line with vsnprintf it works like it should with the .net project, but that one line is what's causing the dll to be unable to load in the .net project.
Incase this is releveant, here are my linker libraries for the dll:
ws2_32
iphlpapi
mswsock
winmm
user32
Also, I feel like it might be important to note that the other day, just before all of this happened, I got an error from codeblocks saying something about my config file being corrupted. This project was building fine before then, but I had to go back and manually re-assign the compiler and linker settings.
Any suggestions?
UPDATE: snprintf is causing the same issue. I can use sprintf and vsprintf, but snprintf and vsnprintf are causing the dll to not be loaded in the C# project, even though the dll will still build with no errors or warnings. I've looked into the calling conventions used to import my dll functions into my c# project, and Cdecl seems like the way to go since it specifically says that it "enables calling functions with varargs, which makes it appropriate to use for methods that accept a variable number of parameters, such as Printf." I've also tried importing SomeFunction using calling conventions Winapi, StdCall and ThisCall, but they all have the same results. Any help would be really appreciated, I have been stumped on this for a while.

COM Callable Wrapper not working when called from delphi program

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.

Passing argument to c# callback from c++

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).

Call a function in a console app from VBScript

I have a console app, myapp.exe. Within the app is a function, let's call it:
public static int AddIntegers(int a, int b)
Is it possible to make this function visible externally so that a VBscript could call it? Do I have to move the function into a DLL or can I leave it in the EXE and make it visible? If so, how?
Idealistically, you should be making a DLL and set Com Visible on the functions you need to expose.
using System;
using System.Runtime.InteropServices;
namespace MyDLL
{
[ComVisible(true)]
public class Operations
{
[ComVisible(true)]
public int AddIntegers(int a, int b)
{
return a + b;
}
}
}
After you've compiled your DLL you need to register it with regasm.exe so that you can call it from VBScript:
Dim myObj
Set myObj = CreateObject("MyDLL.Operations")
Dim sum
sum = myObj.AddIntegers(3, 5)
This reply is based on the CodeProject posting How to call a .NET DLL from a VBScript by Raymund Macaalay. I recommend you read it.
Also, you should check other stackoverflow posting such as How to call C# DLL function from VBScript.
Yes, you will need to make the managed code library (DLL) visible to the VBScript (most likely through the GAC). Then in your VBScript, you can do something like:
dim yourObject = CreateObject("YourContainingObject");
yourObject.AddIntegers yourFirstInt, yourSecondInt

Categories