Tag Archives: C#

Xlua#: How to Call C

Call C in xlua#

1. Premise

The xlua framework is used here. You need to configure xlua in advance and set the loader path;

You can refer to the previous blog: xlua introduction;

//On the call side, all the lua code is written in the LuaCallCSharp.lua file
public class LuaCallCSharp1 : MonoBehaviour
{
    void Start()
    {
        XluaEnv.I.DoString("LuaCallCSharp");
    }

    private void OnDestroy()
    {
        XluaEnv.I.Free();
    }
}

2. Call c# class

Static class

public static class TestStatic
{
    public static void ShowName(string name, int id)
    {
        Debug.Log($"name:{name},id:{id}");
    }
}

--静态类
CS.TestStatic.ShowName("littlePerilla",1012);

Dynamic class

public class NPC
{
    public string name;
    public int attack;

    public NPC(string name,int attack)
    {
        this.name = name;
        this.attack = attack;
    }

    public int Hp { get; set; }

    public void Attack()
    {
        Debug.Log($"attack:{attack},Hp:{Hp}");
    }
}

--类对象
local hero = CS.NPC("Angel",100)
hero.Hp = 110
hero:Attack()

Call unity official API

--创建物体
local go = CS.UnityEngine.GameObject("LuaObj ")
--添加组件
go:AddComponent(typeof(CS.UnityEngine.BoxCollider))

Lua does not support generics. You need to write every possible overload where generics are used;

Call parent and child classes

public class Father
{
    public string name = "father";

    public virtual void Say()
    {
        Debug.Log($"{name}:我在被调用");
    }
}

public class Child :Father
{
    public string name = "child";

    public override void Say()
    {
        Debug.Log($"{name}:我在被调用");
    }
}

local father = CS.Father()
father:Say()

local child = CS.Child()
child:Say()

Class expansion method

The extended class must be a static class, and the class must have the attribute [luacallcsharp]; C# type expansion method;

It will be affected by xlua version and unity version, resulting in call failure. The official recommended version of xlua is 2017 (too outdated);

public class TestExtension
{
    public string Test1()
    {
        return "test";
    }
}

[LuaCallCSharp]
public static class MyExtension
{
    public static void Test2(this TestExtension obj)
    {
        Debug.Log("ExtensionFunc:"+ obj.Test1());
    }
}

local testEx = CS.TestExtension()

print(testEx:Test1())
testEx:Test2()

3. Call c# structure

Structures are similar to classes and have construction methods;

public struct TestStruct
{
    public int id;
    public string name;

    public void Output()
    {
        Debug.Log(id);
        Debug.Log(name);
    }
}

--结构体
local teststrut = CS.TestStruct()

teststrut.id = 12
teststrut.name = "littlePerilla"

teststrut:Output()

4. Call c# enumeration

Enumerate the userdate user-defined data types used;

public enum State
{
    idle = 0,
    walk,
    run,
    attack
}

--枚举使用的userdate自定义数据类型
local state = CS.State.idle

print(state)

--转换获得枚举
print(CS.State.__CastFrom(1))
print(CS.State.__CastFrom("run"))

5. Call the delegation in c#

Static delegate assignment call must be released;

Dynamic delegation is not necessary, but it is best to release it;

Make a null judgment before calling the delegate;

There is no + = or – = method in Lua. Multicast can only be realized through a = a + B;

public delegate void DelegateLua();

public class TestDelegate
{
    public static DelegateLua deStatic;

    public DelegateLua deDynamic;

    public static void Func()
    {
        Debug.Log("静态委托");
    }

    public void Func2()
    {
        Debug.Log("动态委托");
    }
}

--静态委托赋值调用必须释放
CS.TestDelegate.deStatic = CS.TestDelegate.Func
CS.TestDelegate.deStatic()
CS.TestDelegate.deStatic = nil

local func = function ()
	-- body
	print("lua函数替换委托")
end

--lua函数赋值委托
CS.TestDelegate.deStatic = func
--多播委托,确定deStatic不为空,lua没有+=和-=
if(CS.TestDelegate.deStatic ~= nil)then
	CS.TestDelegate.deStatic = CS.TestDelegate.deStatic + func
else 
	CS.TestDelegate.deStatic = func
end

--调用前判定不为空
if(CS.TestDelegate.deStatic ~= nil)then
	CS.TestDelegate.deStatic()
end

CS.TestDelegate.deStatic = nil
--动态委托
local test = CS.TestDelegate()

local func1 = function()
	print("动态委托调用")
end

test.deDynamic = func1
test.deDynamic()
test.deDynamic = nil

6. Call c# event

The call of events cannot be copied directly, but (“+”, function) must be used;

The event callback also needs to be released;

public delegate void EventLua();

public class TestEvent
{
    public event EventLua luaEvent1;
    
    public static event EventLua luaEvent2;

    public static void Func()
    {
        Debug.Log("静态事件");
    }

    public static void CallEvent2()
    {
        if (luaEvent2 != null)
            luaEvent2();
    }

    public void CallEvent1()
    {
        if (luaEvent1 != null)
            luaEvent1();
    }
}

--静态事件
CS.TestEvent.luaEvent2("+",CS.TestEvent.Func)
CS.TestEvent.CallEvent2()
CS.TestEvent.luaEvent2("-",CS.TestEvent.Func)


--动态事件
local test = CS.TestEvent()

local func = function ()
	print("动态事件")
end

test:luaEvent1("+",func)
test:CallEvent1()
test:luaEvent1("-",func)

C# call Python error no module named OS [How to Solve]

C # calling Python

Environment: Windows 8.1, has installed Python 2.7 (C: Python 27), has configured environment variables. Has installed vs2013, vs2017

1. Install ironpython

Download address http://ironpython.net/download/ I downloaded ironpython-2.7.4.3261515540.msi

The installation directory is: F:// program files (x86) – ironpython 2.7

2. Open vs2013 and create a new console program csharpcallpython

3. Add reference

Add a reference to csharpcallpython, ironpython.dll and microsoft.scripting.dll under F: (program files (x86)  ironpython 2.7  platforms  net40

4. Add the PY script file python1.py in csharpcallpython, and select to copy it locally. The code is as follows

def add(num1,num2):
    return num1+num2;

Add code in csharpcallpython

5

ScriptRuntime pyRuntime = Python.CreateRuntime(); //Create a runtime environment

        dynamic obj = pyRuntime.UseFile("Python1.py"); // call a Python file

        int a = 1, b = 2;

        int sum = obj.add(a,b); //call the sum function in the Python file
        Console.Write("Sum:");
        Console.WriteLine(sum);

The running result is sum = 3

This is the end of the call. Thank you. If this is possible, then it is impossible. Please see below

How to reference the third party Library

How to use the Library under OS?Let’s continue to add the PY script file python2.py

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
import shutil


def ClearDirect(path):#

    for root, dirs, files in os.walk(path,topdown=False):
        print 'root',root
        for dir in dirs:

            print 'delete:',os.path.join(root, dir)
            #os.removedirs(os.path.join(root, dir))
            shutil.rmtree(os.path.join(root, dir))


    return 'OK'

The purpose of the script is to delete the subdirectory of the incoming directory and add C code

     ScriptRuntime pyRuntime2 = Python.CreateRuntime(); //Create a runtime environment
        dynamic obj2 = pyRuntime.UseFile("Python2.py"); // call a Python file
        obj2.ClearDirect(@"D:\Data\KkImage\2017"); //
        Console.Write("result");
        Console.WriteLine(sum); 

After running, I’m very sorry for the error

Unhandled exception of type "IronPython.Runtime.Exceptions.ImportException" in Microsoft.Dynamic.dll 

Additional information: No module named os  

The OS module was not found

7. How can I use the OS library

Add in python2.py

import sys
sys.path.append("F:\Program Files (x86)\IronPython 2.7\lib")

Code becomes

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import sys
sys.path.append("F:\Program Files (x86)\IronPython 2.7\lib")
import os
import shutil


def ClearDirect(path):#delete

    for root, dirs, files in os.walk(path,topdown=False):
        print 'root',root
        for dir in dirs:

            print 'delete:',os.path.join(root, dir)
            #os.removedirs(os.path.join(root, dir))
            shutil.rmtree(os.path.join(root, dir))


    return 'OK'

Run again, found subdirectory deleted successfully. Congratulations

8. In the Python code above, add

  sys.path.append("F:\Program Files (x86)\IronPython 2.7\lib")

When the program is released, the path on the server will change. If there are dozens of Python files, do you have to modify the path one by one?It’s horrible to think about it

So, you can use the following method. (first, remove the sentence “sys. Path. Append” in the python file (F: program files (x86) – ironpython 2.7 – lib “)

ScriptRuntime pyRuntime3 = Python.CreateRuntime(); //Create a runtime environment
            var engine = pyRuntime3.GetEngine("python");
            var pyScope = engine.CreateScope();
            var paths = engine.GetSearchPaths();
            paths.Add(@"F:\Program Files (x86)\IronPython 2.7\lib");
            engine.SetSearchPaths(paths);
            dynamic obj3 = pyRuntime3.UseFile("Python2.py"); //Calling a Python file
            obj3.ClearDirect(@"D:\Data\KkImage\2017"); //

If you specify the location of the library in the engine, you don’t need to specify it in each Python file

Transcoding of system.web.httputility.urlencode in C #

Recently, we need to interface with Java program. The URL transcoding problem we encountered is as follows:

The characters generated by urlencoder.encode used in Java URL encoding are uppercase, and the English ‘(‘, ”) are converted to ‘(‘, ‘) 28’ and ‘(‘) 29 ‘ respectively

However, the characters generated by httputility.urlencode in c#are lowercase and the English brackets are not transcoded , so the characters generated by the two are inconsistent, leading to system errors

The solution is posted below:

1. Character case problem:

//Uppercase conversion of transcoded characters does not convert parameters to uppercase (used)
 public static string GetUpperEncode(string encodeUrl)
        {
            var result = new StringBuilder();
            int index = int.MinValue;
            for (int i = 0; i < encodeUrl.Length; i++)
            {
                string character = encodeUrl[i].ToString();
                if (character == "%")
                    index = i;
                if (i - index == 1 || i - index == 2)
                    character = character.ToUpper();
                result.Append(character);
            }
            return result.ToString();
        }
//Other methods searched on the web, by this method instead of calling HttpUtility.UrlEncode directly
private static string UrlEncode(string temp, Encoding encoding)
    {
      StringBuilder stringBuilder = new StringBuilder();
      for (int i = 0; i < temp.Length; i++)
      {
        string t = temp[i].ToString();
        string k = HttpUtility.UrlEncode(t, encoding);
        if (t == k)
        {
          stringBuilder.Append(t);
        }
        else
        {
          stringBuilder.Append(k.ToUpper());
        }
      }
      return stringBuilder.ToString();
    }

2. English bracket question:

//Solved by replacing the string
encodeurl= encodeurl.Replace("(","%28");
encodeurl=encodeurl.Replace(")", "%29");