How to Embed the perl interpreter in a C# Program - c#

I realize that I have to DllImport the perlembed methods
perl_parse
perl_alloc
perl_free
etc.,
But not sure how to marhsall the function arguments for using it with DLLImport especially with perl_parse method.
I also realize that a related question already exists which is almost there but still the OP has solved by created a C wrapper and then using it in C#.
He says that he was not able to DLLimport PERL_SYS_INIT3.
So my question is how to properly wrap them using only C# and use it?

Look at this; I hope it will help (it was called in early version)
I got this from here (perl)
To embed a Perl interpreter in a C# program, add a reference to the COM object "Microsoft Script Control 1.0" and write code like this:
MSScriptControl.ScriptControlClass Interpreter;
Interpreter = new MSScriptControl.ScriptControlClass();
Interpreter.Language = #"PerlScript";
string Program = #"reverse 'abcde'";
string Results = (string)Interpreter.Eval(Program);
The above is equivalent to the following Perl script, which embeds a Perl interpreter within a Perl interpreter:
use Win32::OLE;
my $Interpreter;
$Interpreter = Win32::OLE->new('ScriptControl');
$Interpreter->{Language} = 'PerlScript';
my $Program = "reverse 'abcde'";
my $Results = $Interpreter->Eval($Program);

Related

Boost.Interprocess v1.66 - get_bootstamp segfault with C#

I have problem with Boost.Interprocess (v1.66) library which I use in my C/C++ library which I use in C# through Marshalling (calling C native code from C#).
I found the problem if I was using Boost.Interprocess named_semaphore for sync between processes. (in open_or_create mode)
If I use my C/C++ lib with another native C/C++ code everything works fine (under newest Windows 10, Linux (4+ kernel) and even Mac OS X (>=10.11)).
The problem occurred under Windows - with C# I have C wrapper around C++ code. If I use Marshalling with simple own-build EXE --> Everything works! But If I use The same C# code (with the same C lib) in the third party application as a DLL plugin I got segfault from get_bootstamp in named_semaphore.
So I have third-party C# SW for which I create plugins (C# DLL). In that plugin I use my C library through marshalling. Marshalling work fine in test C# project (which just call C functions from C lib) but same code segfault in third-party SW.
C Library workflow:
Init all necessary C structures
Start desired TCP server (native C/C++ app) using Boost.Process
Wait for server (through named_semaphore) <-- segfault
Connect to the server...
C# code has same workflow.
Found the problem
The problem occured in boost::interprocess::ipcdetail::get_booststamp (which is called in named_semaphore). here:
struct windows_bootstamp
{
windows_bootstamp()
{
//Throw if bootstamp not available
if(!winapi::get_last_bootup_time(stamp)){
error_info err = system_error_code();
throw interprocess_exception(err);
}
}
//Use std::string. Even if this will be constructed in shared memory, all
//modules/dlls are from this process so internal raw pointers to heap are always valid
std::string stamp;
};
inline void get_bootstamp(std::string &s, bool add = false)
{
const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get();
if(add){
s += bootstamp.stamp;
}
else{
s = bootstamp.stamp;
}
}
If I debug to the line
const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get()
booststamp.stamp is not readable. The size is set to 31, capacity is set to some weird value (like 19452345) and the data is not readable. If i step over to
s += bootstamp.stamp;
the segfault occured!
Found the reason
I debug once more and set debug point to the windows_bootstamp constructor entry and I got no hit so the stamp is not initialized (I guess).
Confirmation
If I change get_bootstamp to
inline void get_bootstamp(std::string &s, bool add = false)
{
const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get();
std::string stamp;
winapi::get_last_bootup_time(stamp);
if(add){
s += stamp;
}
else{
s = stamp;
}
}
Recompile my lib and exe - everything works fine (without any problem).
My question is - what I am doing wrong? I read Boost.Interprocess doc really thoroughly but there are no advice/warnings about my problem (yeah there is "COM Initialization" in Interprocess doc but it not seems helpfull).
Or it's just a bug in Boost.interprocess and I may report it to Boost bug tracker?
Notice - if I start server manually (before I run C# code) It works without segfaults

How can I use a C# DLL from Python Script?

I need to use a function in Python(32) from dll written in C#.
I use ctypes, but i got the error message:'can't find z function'. The name of the funct i need is 'z' an lib name is "ledscrcons.dll". I've checked it from another app(C#) and this library works good, but python doesn't see it. I have no idea what is the problem??
Here is the code of PScript:
import sys
import string
from time import gmtime, strftime
from array import *
from ctypes import *
import ctypes
import clr
def SendStr(s, port):
mydll = clr.AddReference('ledscrcons.dll')
from ledscrcons import Class1
send = mydll.z
mydll.z.argtypes = [ctypes.c_char_p, ctypes.c_int]
mydll.z.restype = c_int
st = s.encode('cp1251')
i=2
count = 0
critcnt = 1
while i!=0 and count<critcnt:
i=send(c_char_p(st), c_int(port))
if i==2 :
print(str(i) + "dd")
if i==1 :
print(str(i) + 'dd')
if i==0 :
print('t')
count = count + 1
if count==critcnt:
if i==1:
print('kk')
if i==2:
print('uu')
return i
Please,any help would be usefull.
I guess the library you used is not Com Visible. You can make it Com Visible by setting attribute:
[ComVisible(true)]
You can also try IronPython, which is a .net implementation of Python. In IronPython, simply do
import clr
clr.AddReference('YourAssemblyName')
from YourNameSpace import YourClassName
C#-DLLs are not native executables but need the .NET-Runtime library. So you cannot use them with native Python executables. You have to switch to IronPython which is a python implementation in C#.
You cannot use ctypes to access a .NET assembly.
I would recommend using IronPython or Python .NET

Calling c# dll (which parses XML file) from my c++ application to return array / list to c++

I have a simple c++ Application. This Application is just printing text out.
I have also a c# .dll NET 3.5 which parses complex xml files, extracts values and saves them into a List. Its like 2 Classes with 4 methods. They open a file, parse the xml and store it into a List. When the c# .dll is done, it has a List with 10000 values;
Since i do not want to write the complex parsing XML in c++, i would like to use my c# xml parsing .dll.
Is it possible for me, to call my c# .dll from inside my c++ application, let the c# .dll parse a specified xml file, and return that created List, with the parsed xml values, to my c++ application?
In my c++ application i would proceed to modify the data within the returned list.
edit: i would be using vc++ (Microsoft Visual Studio 2010)
edit2: the vc++ app would be an expension/plug-in to another bigger Application. I would register the plug-in to that bigger application, and every time i press the icon in the menu, my vc++ application would be started
edit3: Has anyone experience with such a task? I kinda need a clear yes or no if it is possible.
edit4: i do want to avoid reading files that have been written by my .net .dll. I want my c++ app to send a string to my .net .dll and receive back a list/array object. Or is this a bad idea and i should do the xml parsing in c++ itself?
Yes, you can do it, but its kinda hard. One way to do it is to use C++ to load up CLR and execute your function, something like this:
code inspired by Blizzhackers.cc
void StartNET()
{
DWORD result;
ICLRRuntimeHost* pCLR = NULL;
CorBindToRuntimeEx(NULL, L"wks", NULL, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pCLR);
pCLR->Start();
pCLR->ExecuteInDefaultAppDomain(L"C:\\myNET.dll", L"myNet.Program", L"Main", L"arg", &result);
pCLR->Stop();
}
This C++ code will execute the int Main(string arg) function from namespace myNet and class Program, by that I mean:
myNET.dll:
namespace myNet
{
class Program
{
int Main(string arg)
{
//and here you can run your XML parser:
List<string> myList = XMLParse();
FileStream fs = new Filestream("xmllist.txt");
StreamWriter sw = new StreamWriter(fs);
foreach(string s in myList)
sw.WriteLine(s);
sw.Close();
fs.Close();
return 1;
}
List<string> XMLParse()
{
//Your code here
return aList;
}
}
}
And after this you could use c++ to get the files from xmllist.txt, something like:
vector<char[]> getList()
{
vector<char[]> *myVector = new vector<char>;
ifstream cin("xmllist.txt");
while(!cin.eof())
{
char line[100];
cin >> line;
myVector.push(line);
}
cin.close();
return myVector;
}
I don't know if this last function works, but you get the general idea.
I created a managed/unmanaged dll in C++ some time ago. (Note though that C++.net has not the easiest syntax.)
Actually, I do not know where to start now, maybe this has the information http://channel9.msdn.com/Forums/TechOff/101918-Mixing-Managed-and-Unmanaged-C-in-a-DLL . It certainly was well possible with.. VS 2005? With that, you can have both managed an unmanaged code in one binary/assembly, and thus call the C# dll.
Apart from that, you can wrap your C# objects as COM objects. http://msdn.microsoft.com/en-us/library/ms404285.aspx . Then you can use COM interop.
In each case, marshalling the input/output would require some trial and error - it is not that obvious if you have never done it before.
Actually, this link should cover it all: http://msdn.microsoft.com/en-us/library/ms973872.aspx .

Embedding IronPython in a C# application - import error on urllib

I have a Python file with as content:
import re
import urllib
class A(object):
def __init__(self, x):
self.x = x
def getVal(self):
return self.x
def __str__(self):
return "instance of A with value '%s'" % (self.getVal())
I also have a simple C# console project with the following code:
engine = Python.CreateEngine();
ScriptSource source = engine.CreateScriptSourceFromFile("test.py");
ScriptScope scope = engine.CreateScope();
ObjectOperations op = engine.Operations;
source.Execute(scope); // class object created
object klaz = scope.GetVariable("A"); // get the class object
object instance = op.Call(klaz, "blabla waarde"); // create the instance
object method = op.GetMember(instance, "getVal"); // get a method
string result = (string)op.Call(method); // call method and get result (9)
Console.WriteLine("Result: " + result); //output: 'Result: blabla waarde'
(I got this from this stackoverflow querstion and answer)
If I leave out the the import urllib statement in the Python file everything works fine. (meaning it finds the re module)
But as soon as i either add import urllib or import urllib2 I get the following exception:
ImportException was unhandled
No module named urllib
So somehow it can't find the urllib. I checked the IronPython lib folder and both urllib and urllib 2 are definitely there.
The same exception gets thrown when I import urllib in the C# code. (engine.ImportModule("urllib");)
Any ideas?
I'd like to manage the imports in the python code and not in the C# code.
(So I'd like to avoid stuff like this: engine.ImportModule("urllib");)
Edit:
Some extra info on what I'm actually going to use this for (maybe someone has an alternative):
I will have a main C# application and the python scripts will be used as extensions or plugins for the main application.
I'm using Python so that I don't need to compile any of the plugins.
I believe that 'Lib' being on sys.path from the interactive console is actually done inside ipy.exe - and when embedding you will have to add the path manually. Either the engine or the runtime has a 'SetSourcePaths' (or similar) method that will allow you to do this.
I face the same problem. Following "Tom E's" suggestion in the comments to fuzzyman's reply I could successfully resolve the issue. The issue seems to be it is not able resolve the location of the urllib.py. We need to set it.
You can check the following link for the question and answer.
The version of CPython you're importing from must match your IronPython version. Use CPython v2.5 for IronPython 2.0, or v2.6 for IronPython 2.6.
Try this:
import sys
sys.path.append(r'\c:\python26\lib') # adjust to whatever version of CPython you have installed.
import urllib

Simplfying DSL written for a C# app with IronPython

Thanks to suggestions from a previous question, I'm busy trying out IronPython, IronRuby and Boo to create a DSL for my C# app. Step one is IronPython, due to the larger user and knowledge base. If I can get something to work well here, I can just stop.
Here is my problem:
I want my IronPython script to have access to the functions in a class called Lib. Right now I can add the assembly to the IronPython runtime and import the class by executing the statement in the scope I created:
// load 'ScriptLib' assembly
Assembly libraryAssembly = Assembly.LoadFile(libraryPath);
_runtime.LoadAssembly(libraryAssembly);
// import 'Lib' class from 'ScriptLib'
ScriptSource imports = _engine.CreateScriptSourceFromString("from ScriptLib import Lib", SourceCodeKind.Statements);
imports.Execute(_scope);
// run .py script:
ScriptSource script = _engine.CreateScriptSourceFromFile(scriptPath);
script.Execute(_scope);
If I want to run Lib::PrintHello, which is just a hello world style statement, my Python script contains:
Lib.PrintHello()
or (if it's not static):
library = new Lib()
library.PrintHello()
How can I change my environment so that I can just have basic statments in the Python script like this:
PrintHello
TurnOnPower
VerifyFrequency
TurnOffPower
etc...
I want these scripts to be simple for a non-programmer to write. I don't want them to have to know what a class is or how it works. IronPython is really just there so that some basic operations like for, do, if, and a basic function definition don't require my writing a compiler for my DSL.
You should be able to do something like:
var objOps = _engine.Operations;
var lib = new Lib();
foreach (string memberName in objOps.GetMemberNames(lib)) {
_scope.SetVariable(memberName, objOps.GetMember(lib, memberName));
}
This will get all of the members from the lib objec and then inject them into the ScriptScope. This is done w/ the Python ObjectOperations class so that the members you get off will be Python members. So if you then do something similar w/ IronRuby the same code should basically work.

Categories