Using .PYD file in C#? - c#

I am developing a program using C#, but I just figured out that what I am going to program is very very difficult in C# yet easy in Python. So what I want to do is make a .PYD file and use it in C# program, but I don't know how. I've been searching about it but I couldn't find anything.
So these are my questions: How do I use .PYD file in C#? I know that .PYD files are similar to .DLL files, so are .PYD files still usable in computers that have no Python installed?

A .pyd file IS a DLL but with function init*() where * is the name of your .pyd file. For example, spam.pyd has a function named initspam(). They are not just similar, but the same! They are usable on PCs without Python.
Do not forget: builtins will NOT be available. Search for them in C, add them as an extern in your Cython code and compile!

Use pythonnet
Tutorial
You need a GIL state.
using (Py.GIL())
{
// Your code here
}
Inside the GIL block, create a scope.
using (Py.GIL())
{
using (PyScope scope = Py.CreateScope())
{
// Your code here
}
}
To execute code:
scope.Exec(codeStr);
To set a variable:
scope.Set(name, value); // 'name' is a string and 'value' is a 'PyObject' object.
To convert to PyObject:
obj.ToPython()
Convert to PyObject if you need to put your object into Python.
To evaluate[0][1][2][3][4] an expression:
scope.Eval(expr)
To get a variable[5][6] value:
scope.Get(variableName)
C# code that doesn't have an end semicolon before any comment and is one-line represents an expression.
References
0: https://codereview.stackexchange.com/questions/160524/evaluating-arithmetic-expressions1: https://www.programiz.com/python-programming/methods/built-in/eval2: What does Python's eval() do? on SO3: https://docs.python.org/3/reference/expressions.html4: Python - Evaluate math expression within string on SO5: https://realpython.com/python-variables6: https://www.w3schools.com/python/python_variables.asp

Related

How to save a plot generated via R.NET to a file on disk?

I am using R.NET to generate plots (using ggplot) and I want to save these graphs in PNG format on disk. Whenever I call engine.Evaluate("ggsave('C:\path\to\file.png', myPlot)") the program abruptly aborts with exit code 2 without anything being written to disk; no error is displayed when this happens. It is also not possible to write the plot to a file using png() or pdf(). This problem is not specific to ggplot, however - I also cannot store plots generated via the native plot function.
I could narrow down the problem to the line containing either ggsave() or png()/pdf(): when this line is executed, the program aborts. Since I can actually see the plots generated by both, ggplot() and plot(), the plotting itself does not seem to be the issue.
You should be able to recreate what I described using the following C# code:
using RDotNet;
namespace Test {
class Program {
static void Main(string[] args) {
REngine.SetEnvironmentVariables();
REngine engine = REngine.GetInstance();
engine.Evaluate("png('D:\\Test.png')");
engine.Evaluate("plot(rnorm(1000))");
engine.Evaluate("dev.off()");
}
}
}
Apparently, this code should work without any issues.
When running
png('D:\\Test.png')
plot(rnorm(1000))
dev.off()
in R, a plot is generated and saved to Test.png successfully.
I am using .NET Framework 4.6.1, R.NET 1.7.0, and R 3.4.2. R is not installed on my computer and registry entries have not been created for R - I am just using the R DLLs as described here.
It's not that you cannot have backslashes as you mention in your answer. Although forward slashes solve your problem as well, I think it might help in the future if I explain the other solution.
You have to escape your backslash twice.
Once for C#, once for R.
Calling Evaluate like this
engine.Evaluate("png('D:\\Test.png')");
will call the R engine with the string: "png('D:\\Test.png')", which, if you evaluate it is just: png('D:\Test.png'). If you typed that into R you'd get an error as well.
If you want to run the R command png('D:\\Test.png'), you have to escape that string, which has two backslashes after escaping both it becomes: "png('D:\\\\Test.png')".
Turns out, you cannot have backslashes in the image file's path. If you want to write an image to a file on disk, you have to use forwardslashes, e.g. instead of
engine.Evaluate("png('D:\\Test.png')");
use
engine.Evaluate("png('D:/Test.png')");
Maybe this is still helpful for someone else.

C# to Python (not IronPython) Sending and Recieving Array's, Int, String, Decimals

I have been researching a simple way to start a Python (not IronPython) script and pass parameters such as an Array, String, Int, Decimal and then retrieve an output such as an array from the Python script.
All research points to very complicated methods that are unreliable or IronPython which is limited.
If VBA can do this via xlwings (really well), why cant C# within Visual Studio?
Any advise, links or an example would be really helpful. Thank you
As #denfromufa mentioned, Pythonnet is the way to go. Here is how you can start a module and pass objects to it from C#.
Note:
numpy is given here for example but you can replace it with any other module, even a custom one.
an array object is showed as example but it is the exact same thing for string, double, int, etc.
In this example I execute everything directly in the Python engine using PyScope, since your question was from C# to Python. If you need the object on the C# side, you can use dynamic types instead and import the module with Py.Import().
using Python.Runtime;
double[] a = [2.1, 3.5, 5.4];
using (Py.GIL())
{
using (PyScope scope = Py.CreateScope())
{
scope.Exec("import numpy as np");
scope.Set("a", a.ToPython())
scope.Exec("b = np.array(a)");
}
}

How to convert string to Expression ? Using string in text file as formulas for different game variables

I'm using Unity with C#. Creating a resource management game.
I need an Index system. ie. Food Happiness index, Food Variety idex.
Each index would have different formulas.
I don't want to hardcode each indexes.
I'm looking for parsing solutions that would allow me to store the formulas as string in JSON. And evaluate these formulas during runtime.
foodhapiness = (resourceDic["food"].Production/esourceDic["food"].Consumption) * foodVariety;
foodVariety = resourceDic["fish"].count/resourceDic["meat"].count;
Also, I'm thinking of letting user add their own indexes as well. - Create text file(json) with formulas and the game should load the text file and evaluate. Like a mod.
I tried using several Expression Evaluator solutions which would have been the solution but they appear to not be working with Unity.
FLEE : Error at compile. FileNotFoundException: Could not load file or assembly 'Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral,
C# Expression Evaluator : Won't compile. This one Unity says something like can't load library bundle.
In Javascript, there's an Eval() function. But someone pointed out that it's risky since this allow user to run any function also I need C# solution.
It feels like I'm coming at this in the wrong way. Anyone have a better solution for something like this ?
Used NLua. It works.
https://github.com/Mervill/Unity3D-NLua
-execute Lua script stored in a string to accessing C# Properties
Don't know about the performance though.
Leave this here if anyone google and ... keywords happen to match topic name which is unlikely.. anyway.

how to read constants from .h file in C#

I want to read the constants in C#, these constants are defined in a .h file for C++. Can anyone tell me how to perform this in C# ? The C++ .h file looks like:
#define MYSTRING1 "6.9.24 (32 bit)"
#define MYSTRING2 "6.8.24 (32 bit)"
I want to read this in C# ?
Here is a really simple answer that you can use on each line of your .h file to extract the string value.
string GetConstVal(string line)
{
string[] lineParts = string.Split(line, ' ');
if (lineParts[0] == "#define")
{
return lineParts[2];
}
return null;
}
So any time it returns null, you don't have a constant. Now keep in mind that it is only getting the value of the constant, not the name, but you can easily modify the code to return that as well via out parameter, etc.
If you want to represent other data types, like integers, etc. you will have to think of something clever since macros in C++ don't really count as type safe.
You have two options:
1- Create a C++ wrapper code, which wraps these macros, export this code to a lib or dll and use it from C#.
2- read/parse the .h file from your code, and get the values at run-time.

adding stock data to amibroker using c#

I have had a hard time getting and answer to this and i would really , really appreciate some help on this.
i have been on this for over 2 weeks without headway.
i want to use c# to add a line of stock data to amibroker but i just cant find a CLEAR response on how to instantiate it in C#.
In VB , I would do it something like;
Dim AmiBroker = CreateObject("Broker.Application")
sSymbol = ArrayRow(0).ToUpper
Stock = AmiBroker.Stocks.Add(sSymbol)
iDate = ArrayRow(1).ToLower
quote = Stock.Quotations.Add(iDate)
quote.Open = CSng(ArrayRow(2))
quote.High = CSng(ArrayRow(3))
quote.Low = CSng(ArrayRow(4))
quote.Close = CSng(ArrayRow(5))
quote.Volume = CLng(ArrayRow(6))
The problem is that CreateObject will not work in C# in this instance.
I found the code below somewhere online but i cant seem to understand how to achieve the above.
Type objClassType;
objClassType = Type.GetTypeFromProgID("Broker.Application");
// Instantiate AmiBroker
objApp = Activator.CreateInstance(objClassType);
objStocks = objApp.GetType().InvokeMember("Stocks", BindingFlags.GetProperty,null, objApp, null);
Can anyone help me here?
Thanks
The VB code uses something called late binding against a "COM IDispatch" compatible component. Late binding is not supported by C# (up to C# version 3). The C# compiler only compiles code it knows how bind to (called early bind).
To do what you want to do, it would be easier to generate a proxy dll via Visual Studio - select add reference on a project, then select the tab COM, and then search for that ami broker component in the list. This will generate a proxy dll which you can program against using similar code as the one you have showed for VB.
In C# 3.0, you'll discover that you sometimes have to use Type.Missing and that you have to do some additional explicit casting, even though you'd think that it doesn't seem logical.
C# 4.0 has something called dynamic, which allows you to write much cleaner code when accessing COM components.
See my answer here for the code:
https://stackoverflow.com/a/20101274/1581495
I actually use this method now. I save text files from MetaTrader then import them realtime into AmiBroker. Doing it this way is essentially like importing quotes using the ASCII import, so you'll need to make sure that you prepare your import format file. For me, a line of sample data looks like this:
EURAUD,20170607,00:00:00.4885,1.50174,1.50231,1 //Symbol, Date, Time (HH:MM:SS.tttt), Bid, Ask, Volume
I use the default.format file, which looks like this:
$FORMAT TICKER,DATE_YMD,TIME,CLOSE,AUX1,VOLUME
$SEPARATOR ,
$AUTOADD 0
$BREAKONERR 0
$SKIPLINES 0
Find the guide and some examples here on importing and formats:
https://www.amibroker.com/guide/d_ascii.html
EDIT: this might also help with importing
http://www.amibroker.com/kb/2016/01/23/how-to-create-custom-import-definition-for-ascii-importer/

Categories