c# 调用c++ && c++调用c# 函数

这几天又开始了用 c#写窗口程序,自认为用c#做窗口程序太简单了,比那什么mfc简单太多,当然可能QT等库也是比较简单,我就懒得去学习了。


        //[return: MarshalAs(UnmanagedType.LPStr)]
        //[MarshalAs(UnmanagedType.LPStr)]


废话短说,我做一个服务器测试程序,也只有跟用户交互的部分是使用的c#窗口,其他都是c++ dll。

然后肯定会出现c#调用c++的问题,这个很容易解决,c#代码的写法如下:

        [DllImport("TestCommand.dll", EntryPoint = "StartRun", CallingConvention=CallingConvention.StdCall)]
        public static extern int StartRun(string ip, UInt16 port, StringBuilder out_err_msg, int msg_buffer_length); 

        [DllImport("TestCommand.dll", EntryPoint = "Register", CallingConvention=CallingConvention.StdCall)]
        public static extern int Register(string name_or_tel, string pwd, int reg_type, StringBuilder out_err_msg, int msg_buffer_length); 

那么c# 如何调用:

        private void RunNetIO(string ip, UInt16 port)
        {
            ThreadSynUIFunc ui_func = new ThreadSynUIFunc(ThreadSynUIFuncImpl);
            this.Invoke(ui_func, new object[] { eUIControl._register, false });

            StringBuilder out_err_msg = new StringBuilder(512);
            int ret_val = ImCommand.StartRun(ip, port, out_err_msg, 512);
            if(ret_val != Common.RET_INT_OK)
            {
                MessageBox.Show(out_err_msg.ToString());
            }

            this.Invoke(ui_func, new object[] { eUIControl._register, true });
        }

        private void ThreadSynUIFuncImpl(eUIControl ui, bool enabled)
        {
            switch(ui)
            {
                case eUIControl._register:
                    bt_connect.Enabled = enabled;
                    break;
            }
        }

        private void button_register_Click(object sender, EventArgs e)
        {
            int reg_type = Convert.ToInt32(rb_name.Tag);
            if (rb_tel.Checked) { reg_type = Convert.ToInt32(rb_tel.Tag); }
            StringBuilder out_err_msg = new StringBuilder(512);
            int ret_val = ImCommand.Register(tb_name_tel.Text, tb_pwd.Text, reg_type, out_err_msg, 512);
            if (ret_val != Common.RET_INT_OK)
            {
                MessageBox.Show(out_err_msg.ToString());
            }
        }
    }



cpp的写法:

int AssignReturnVal(char* d, int d_len, const char* s, int return_val)
{
	int s_len = strlen(s);
	if (s_len > d_len)
	{
		s_len = d_len;
	}
	strncpy_s(d, d_len, s, s_len);
	return return_val;
};

template<class Func, class... Args>
int ExecImpl(Func func, char* out_err_msg, int in_msg_buffer_length, Args... args)
{
	try{ func(args...); }
	catch (const char* ex){ return AssignReturnVal(out_err_msg, in_msg_buffer_length, ex, RET_INT_FAIL); }	
	catch (std::exception ex){ return AssignReturnVal(out_err_msg, in_msg_buffer_length, ex.what(), RET_INT_FAIL); }
	return AssignReturnVal(out_err_msg, in_msg_buffer_length, RET_STR_OK, RET_INT_OK);
}


extern "C"
{
	TESTCOMMAND_API int __stdcall StartRun(const char* ip, 
		uint16_t port, char* out_err_msg, int in_msg_buffer_length)
	{
		if (!ip || strlen(ip) == 0 || port <= 1000)
		{
			AssignReturnVal(out_err_msg, in_msg_buffer_length, "ip or port invalid.", RET_INT_FAIL);
		}
		return ExecImpl(std::bind(&BoostNet::Run, &BOOSTNET, ip, port), out_err_msg, in_msg_buffer_length);
	}

	TESTCOMMAND_API int __stdcall Register(const char* name_or_tel,
		const char* pwd, int reg_type, char* out_err_msg, int in_msg_buffer_length)
	{
		return ExecImpl(NetCommand::Register, out_err_msg, in_msg_buffer_length, name_or_tel, pwd, reg_type);
	}

}



就这样没什么难度,那么如果c++要调用c#函数呢,比如来消息了,c++网络层总要通知c#窗口吧。

比如c++想要传递给c#:

typedef void (__stdcall *FUNC_ARGC_3)(uint64_t msg_id, const char* title, const char* des);
FUNC_ARGC_3 _g_func_3 = nullptr;
那么,c++该怎么写,c# 该怎么写?

ok,下面展示2个例子,不但是供我以后参考,也希望帮助些朋友。

第一部分:

------------------------------------------------

cpp文件:

typedef void (__stdcall *FUNC_ARGC_3)(uint64_t msg_id, const char* title, const char* des);
FUNC_ARGC_3 _g_func_3 = nullptr;

extern "C"
{
	TESTCOMMAND_API void __stdcall SetCallBackFunc(void* func, int argc)
	{
		switch (argc)
		{
		case 3:
			_g_func_3 = (FUNC_ARGC_3)func;
			return;
		}
	}
}

h文件:
extern "C"
{
	//typedef void(*FUNC_ARGC_3)(uint64_t msg_id, const char* title, const char* des);
	TESTCOMMAND_API void __stdcall SetCallBackFunc(void* func, int argc);
}

关键部分,c#:

        //typedef void(*FUNC_SENDFAIL_CALLBACK)(int);
        public delegate void FUNC_SET_CALLBACK_SENDFAIL(int proto_id);
        [DllImport("TestCommand.dll", EntryPoint = "SetSendFailedCallbackFunc", CallingConvention = CallingConvention.StdCall)]
        public static extern void SetSendFailedCallbackFunc(FUNC_SET_CALLBACK_SENDFAIL func);

        //typedef void(*FUNC_ARGC_3)(uint64_t msg_id, const char* title, const char* des);
        public delegate void FUNC_SET_CALLBACK_3(UInt64 msg_id, string title, string des);
        [DllImport("TestCommand.dll", EntryPoint = "SetCallBackFunc", CallingConvention = CallingConvention.StdCall)]
        public static extern void SetCallBackFunc_3(FUNC_SET_CALLBACK_3 func, int argc);

        public Form1()
        {
            InitializeComponent();

            ImCommand.SetSendFailedCallbackFunc(new ImCommand.FUNC_SET_CALLBACK_SENDFAIL(Callback_sendfail));
            ImCommand.SetCallBackFunc_3(new ImCommand.FUNC_SET_CALLBACK_3(Callback_argc_3), 3);
        }

        private void Callback_sendfail(int proto_id)
        {
            MessageBox.Show(string.Format("send msg[{0}] fail.", proto_id));
        }

        private void Callback_argc_3(UInt64 msg_id, string title, string des)
        {
            MessageBox.Show(string.Format("[{0}:{1}]", msg_id, des), title);
        }

注意:或许你可能发现,c#多了一部分代码,多的那一部分对应的c++代码将在下面展示,下面第二部分就不在展示c#代码了!!! 请各就各位。


第二部分的c++代码:

-----------------------------------------------

h:

extern "C"
{
	//typedef void(*FUNC_SENDFAIL_CALLBACK)(int);
	TESTCOMMAND_API void __stdcall SetSendFailedCallbackFunc(void* func);
}

cpp:

typedef void(__stdcall *FUNC_SENDFAIL_CALLBACK)(int);
FUNC_SENDFAIL_CALLBACK _g_func_send_fail_callback = nullptr;

extern "C"
{
	TESTCOMMAND_API void __stdcall SetSendFailedCallbackFunc(void* func)
	{
		_g_func_send_fail_callback = (FUNC_SENDFAIL_CALLBACK)func;
	}
}


ok,希望 我的废话不多,能给朋友一些直接参考!

没有更多推荐了,返回首页