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

9 篇文章 0 订阅

这几天又开始了用 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,希望 我的废话不多,能给朋友一些直接参考!
--------------------- 
作者:oiooooio 
来源:CSDN 
原文:https://blog.csdn.net/oiooooio/article/details/48368329 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值