I have the problem loading the DLL file and calling the functions in Python.
I have tried a lot of tutorials, but still can't figure out how it works.
This is my class to export as DLL file. I use simple C# code.
namespace DemoClassLib
{
public class cLib
{
public int increment(int x)
{
return x + 1;
}
}
}
After building the C# code, I get the DLL file called "DemoClassLib.dll".
I use ctypes to load the DLL file. Everything is okay until now.
from ctypes import *
myDll = WinDLL('D:\\Resources\\DemoClassLib\\bin\\Debug\\DemoClassLib.dll')
Starting from that point, I can't continue.
All the commands I have tried are failed.
n = c_int(1)
myDll.increment(n)
It keeps on showing me the errors.
How can I call the method "increment()" in Python?
And how can I pass the input and retrieve the output from that?
I am very new to Python.
Can someone help me please?
I would be very appreciated if you can provide me the source code tutorial.
You can't do this with ctypes because there is no symbol in the binary called simply "increment", as your increment method is a member of a class. Even if this were C++ the name would be mangled. But with C# you don't even get a mangled name in the symbol table because the code is interpreted by the .NET framework.
If you must for some reason interface with a C# library you may want to consider trying IronPython (http://ironpython.net/) which is Python running on the .NET framework with full access to the CLR. The comment above suggesting exposing a COM interface could also work.
Related
I've written a lot of Python (and a bit of C/C++ many years ago) but am now staring on C# (.NET).
I'm using VSCode as my IDE.
I have the following folder structure
test/
├─ Program.cs
├─ Car.cs
with
//Program.cs
class Progam
{
static void Main(string[] args)
{
Console.Write("Hello SO!");
}
}
and that runs fine when I press CTRL+F5 (Run without debugging).
I've then moved into classes in C#, which is the Car.cs file.
I have an error (I forgot a semicolon)
//Car.cs
class Car
{
string color = "red";
int n_wheels = 4 // Wups, missing semicolon
}
Note, I haven't changed the Program.cs file, but now when I press CTRL+F5 I get the error
C:\Users\Me\Documents\C#\test\Car.cs(8,21): error CS1002: ; expected [C:\Users\Me\Documents\C#\test\Test.csproj]
I might still quite have understood how .NET/C# compiles the stuff and runs the program, but I just wonder, why it throws an error in the Car.cs when that class isn't used at all in the Program.cs, which is the only file that contains a Main function.
I could understand if I've imported the Car file but I do not - I don't use it anywhere and it does not have a Main function.
So my question is; how do I avoid such stuff, when I have files that I'm currently developing (but am not using) that might have some bugs/issues due to it being under construction?
Following up on the comments, and after viewing the OP's bio I can see where this question is coming from.
You are comparing python's execution path to C#'s.
In python (yes, I know python is compiled - I'm simplifying):
The interpreter is going over the commands in a sequential manner and executing them.
i.e. If you have an import within a function - the interpreter will not know or care about the import until it is required, and thus code with bad syntax in another module (= file, for C# speakers) will not affect your program.
C# works a bit differently. The first step is compiling the code and creating a binary file which will be executed.
That file is the binary representation of all the source code files referenced in your project.
Hence:
Any file that has syntax error will fail the project compilation
The binary will not build.
You will not be able to execute the binary.
This is why a syntax error in any file will not allow you to execute your code.
Another way to think about is is that in python the imports are done in run time, while in C# its in compile time.
In both cases a malformed reference file will break the process.
C# simply does it earlier.
So my question is; how do I avoid such stuff
Well, you can fix the syntax error, or comment that part out until you get to it...
I have a complicated Matlab function which I would not like to re-write in C#. The function returns an array of N double-precision numbers.
Given that I have compiled the function to into a .NET assembly (a .dll file), and that the function's signature goes like [resutls] = myFunc('stringInput'), how can I call my function inside a C# code?
Thanks!
Here you can find the steps to do that:
https://www.mathworks.com/help/compiler_sdk/gs/create-a-cc-application-with-matlab-code-1.html
Is necessary have the runtime library installed on the computer that run your code (you can add it when create the .dll package)
The way I did it, is by adding MLApp as a project reference.
From MATLAB, you need to start the automation service:
enableservice('AutomationServer', true);
And within C# you can connect to Matlab using.
MLApp.DIMLApp matlabInstance = (MLApp.DIMLApp)Marshal.GetActiveObject("Matlab.Desktop.Application");
You can then use the interface functions of MLApp to interact. E.g.
int a = (int)matlabInstance.GetVariable("variableName", "base");
Or even execute stuff. E.g.:
matlabInstance.Execute("evalin( 'base' , 'plot( range , dataVector , ''k'');' );");
of course you need some error handling, etc. Normal application stuff.
There's a topic about it here
I currently have the following setup:
Application (executable)
C++ DLL (contains logic used by the executable and loads the C# DLL, temporarily has a console window for debugging)
C# DLL (contains GUI)
The C# DLL uses a nuget package called UnmanagedExports in order to provide functions to C++. The method ShowGui() is provided by C#.
The C# DLL is loaded using LoadLibrary() and the ShowGui() method works correctly. However, I seem to have trouble understanding how I would go by implementing a function that allows C++ to send a message to C#.
Currently I came up with the following:
[DllExport("AddDebug")]
public static void AddDebug([MarshalAs(UnmanagedType.LPStr)]StringBuilder s)
{
guiMain.AddToTextbox(s.ToString()); // the GUI uses BeginInvoke to prevent cross-thread exceptions.
}
In C++ I have simply changed printf() to AddDebug() and this seems to work only half the time: at a certain point the C++ DLL gets blocked when trying to call AddDebug() and gets unresponsive.
I have used the following to debug in C++ (obviously calling sendDebug instead of AddDebug):
sendDebug(string s)
{
cout << s;
AddDebug(s);
cout << s;
}
In the scenario of C++ blocking, the above code only displays the string s once and is never displayed by C#. Meaning AddDebug() is never completed.
I have tried looking for solutions but it doesn't seem to work the way I want it to. Changing to a complete C# solution is not an option as the C++ code is insanely large and would take too much time to "convert".
I hope my question is clear and that somebody maybe has a suggestion to keep me from pulling my hair out. Thanks in advance.
Eventually I ended up implementing a Named Pipe. C# being the server and C++ being the client. Seems to work without any issues.
I have a C# class library that contains some specialized mathematical functionality relating to raster processing (it uses some asynchronous techniques to spped up the processing). I have a project that my client wants written using Ruby on Rails (RoR) on a Linux box, that can benefit from using this library (I'd rather not port it to Ruby or C++).
The first part of my question is:
Can a standalone Mono-based DLL be created from my C# DLL? (By standalone I mean, the DLL can be utilized WITHOUT having mono installed (all required libraries would be included in the single DLL)?
And the second part, if the answer to part 1 is 'yes', can this standalone mono-based DLL be called from Ruby?
EDIT 11/22/2014
I have made a little progress possibly. I have created a *.so file by using
mono --aot -O=all dlltest.dll
(Obviously I now have Mono installed on my Ubuntu test VM.) This results in dlltest.so, which I then add a symbolic link for in /usr/lib.
The code for my test Ruby script is:
require 'ffi'
module CsharpTest
extend FFI::Library
ffi_lib 'dlltest.so'
attach_function :Hello, [], :string
end
ret_str = CsharpTest.Hello()
puts ret_str
Note that my simple C# class is:
using Systems;
namespace DllTest
{
public static class MyClass
{
public static string Hello()
{
return "Hello World";
}
}
}
When I run the test Ruby script (ruby test.rb) I get the following error:
....:in 'attach_function': Function 'Hello' not found in [dlltest.so] (FFI::NotFoundError)
Using 'nm -Ca dlltest.so' the available functions are listed. One of them is '0000000000001010 t DllTest_MyClass_Hello'. If I use this label as opposed to 'Hello' I get a similar error.
Also note that 'nm -D --defined-only dlltest.so' does not list any functions with 'Hello' in them.
I'm still not sure if I've on the right track, but is there anything more I can try? Or is this approach a dead end?
My company currently has a product that uses crystal reports. These reports make a call out to a custom C++ dll (CRUFL) with a lot of business logic for populating certain fields on the crystal reports. My company wishes to have the product switched to use Reporting Services instead of crystal reports and I have been tasked with investigating how to re-use the CRUFL dll with reporting services.
My following question deals specifically with the investigation path I've taken so far, but I would be more than open to any and all suggestions on how else to solve this issue.
On another product we already use reporting services and make custom code calls from the rdl files to a C# dll. Armed with this knowledge, I thought I should be able to write a C# wrapper dll that makes P\Invoke calls to the C++ dll.
I started by writing my own C++ code (to keep it simple) and added a very basic method to return some text (it may be clear that I know only the most basic of C++). In my CPPFile.cpp I have:
extern "C"
{
__declspec(dllexport) void ReturnTextFromDLL(char* & rtnStr)
{
rtnStr = "Some return string from inside the cpp dll! \n";
}
}
I then wrote a C# wrapper both containing the call to the c++ method above as well as a testing method that doesn't make a call to c++:
public static class WrapperClass
{
[DllImport("TestCPP.dll")]
public static extern void ReturnTextFromDLL(out string output);
public static string DisplayHardcodedText()
{
return "Some hardcoded text in WrapperClass";
}
}
Now, I created a simple RDL with two textboxes. Under Report Properties, I added a reference to my C# dll (CSharpWrapper) and added the following under code:
Shared Function GetTextFromCPP() As String
Dim rtnStr As String = ""
CSharpWrapper.WrapperClass.ReturnTextFromDLL(rtnStr)
Return rtnStr
End Function
Shared Function GetHardCodedTextFromWrapper() As String
Return CSharpWrapper.WrapperClass.DisplayHardcodedText()
End Function
For the textboxes' Expression, I have:
=Code.GetTextFromCPP()
and
=Code.GetHardCodedTextFromWrapper()
I also copied both the C++ and C# dll into my \Common7\IDE\PublicAssemblies.
When I preview the report, the textbox that calls GetHardCodedTextFromWrapper() displays 'Some hardcoded text in WrapperClass'.
However, the textbox that should be displaying the text from the C++ method only shows "#Error". In the output window I get:
"The Value expression for the textrun 'Textbox2.Paragraphs[0].TextRuns[0]' contains an error: System.Security.Permissions.SecurityPermission"
I did take this one step back and tested outside of reporting services by writing a quick C# console application and it worked without issues.
I also tried fully deploying the report with the report manager & deploying my dlls to the \ReportServer\bin but it gave the exact same result.
So I guess what I'm asking is if it is even possible in reporting services to do this? If so, what do I need to do to get passed the SecurityPermission?
Thanks in advance for any help with this issue.
Based on the exception you are probably not running in "full trust" which is required to call unmanaged code. If you are hosting this in IIS you will need to change the application pool configuration, if you are running from a standalone executable you will need to change the trust level in the project settings.
You need to reference the new DLL assembly in the RDL file. Example:
<CodeModules>
<CodeModule>DLL INFO</CodeModule>
</CodeModules>
For more info:
https://msdn.microsoft.com/en-us/library/ms159238.aspx
If you're using VS, you can just go to the design view > Report Properties > References > Add Assemblies