码迷,mamicode.com
首页 > 编程语言 > 详细

Interop(交互) Between C# and C++ 研究一

时间:2015-07-08 16:37:54      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:动态规划   android   

 在进行这一个研究前,首先得有一个思想:语言只是一个工具,不同的语言在不同的平台与环境下发挥不同的作用,而你的权利是在选择.有一次我要开发一个关于视频点播系统(事实上这一个系统没什么用处)的时候,发现C#不是很合适进行对Directshow的开发.一个方面是directxC#环境下对Directshow的支持比较少,另一个方面是在存在Directshow.net(一个开源项目,是把directshow封装在.Net环境下调用)情况下,如果你想用它来写SourceFilter的话还是显得有点困难,因为你不是很容易调用系统较底层一点的API,都得用C#封装一下很麻烦.然后后面写这一个文章的动机可能是我自己个人的问题,我总是认为用C++做出来的界面难度大且不好看,但对C#来说就会很不一样,想开发成像vs2005界面那样左右都有可隐藏的窗口都要比用C++开发一个简单界面容易些.所以最后面这一个系统的开发方案是用C++实现directshowsource filter与网络通信,然后通过COM技术封装成一个Player.dllC#调用.而在此过程当中会遇到很多C++C#的通过COM实现相互调用的问题,我便在此总结了一下我的研究结果,有的也许也没有最终最好的答案,有的研究也许在这里只到一半便放弃了,总之这里是我在寻找思路与解决方案的过程.

         有了这一个方案后先开始写一个小小的test:

技术分享
技术分享项目名:InteropWithCSharpAndCPP
技术分享    file1.h:
技术分享        
#pragma once
技术分享        
技术分享        #ifdef __WinTest_C_DLL
技术分享        
#else
技术分享        
#define __WinTest_C_DLL extern "C"  _declspec(dllimport)
技术分享        
#endif
技术分享        __WinTest_C_DLL 
int  add(int a,int b);
技术分享    file1.cpp:
技术分享        #include 
"file1.h"
技术分享        
技术分享        
int  add(int a,int b)
技术分享        
{
技术分享            
return a+b;
技术分享        }

技术分享然后再写了一个C
++ test 项目:cpptest1
技术分享    cpptest1.cpp:
技术分享        #include 
"stdafx.h"
技术分享        
技术分享        #include 
"file1.h"
技术分享        
技术分享        
using namespace std;
技术分享        
技术分享        
int _tmain(int argc, _TCHAR* argv[])
技术分享        
{
技术分享            cout
<<add(4,2)<<endl;
技术分享            getchar();
技术分享            
return 0;
技术分享        }

技术分享        
技术分享        
技术分享引用InteropWithCSarpAndCPP.lib与文件file1.h总后输出6测试成功.
技术分享然后又再写了一个C#的测试项目:charptest1
技术分享    Program.cs:
技术分享        
using System;
技术分享        
using System.Collections.Generic;
技术分享        
using System.Text;
技术分享        
技术分享        
using System.Runtime.InteropServices;
技术分享        
技术分享        
namespace charptest1
技术分享        
{
技术分享          
class Program
技术分享          
{
技术分享            [DllImport(
"InteropWithCSharpAndCPP.dll")]
技术分享            
public static extern int add(int a, int b);
技术分享            
static void Main(string[] args)
技术分享            
{
技术分享              Console.WriteLine(add(
24));
技术分享              Console.Read();
技术分享            }

技术分享          }

技术分享        }

技术分享同时把InteropWithCSharpAndCPP.dll放到charptest1 bin 目录下,也测试成功.
技术分享
 

第一个测试成功,心想这事应该还比较好办.但接着一个问题,就是类的问题,最终Player.dll肯定不可能都用这一种方法的方式给C#调用吧?便开始了第二个简单测试,也就是上面的一个升级版本.突然一想在C#当中调用C++里面的类,还真不太好办,因为DllImport还真不能直接把一个类extern出来,不过后面想到这一种最简单的方法:

技术分享
Project:WinTest3
    Files:
    Math.h
        
#pragma once
        
         
extern "C"  _declspec(dllimport) class  Math
        {
        
public:
            
static Math* instance();
            
int sub(int a,int b);
         
static     void deleteMath(void *);
         
void output(int a,int b);
        
private:
            Math(
void);
            
virtual ~Math(void);
        };
    Math.cpp
        #include 
"Math.h"
        #include 
<Windows.h>
        #include 
<iostream>
        #include 
<strstream>
        #include 
<sstream>
        
        
using namespace std;
        
        Math::Math(
void)
        {
        }
        Math
* Math::instance()
        {
            
return new Math();
        }
        
void Math::deleteMath(void  * m)
        {
            Math 
* mIn=(Math*) m;
            delete mIn;
        }
        
int Math::sub(int a,int b)
        {
            
return a-b;
        }
        
void Math::output(int a,int b)//当时随兴突然想在GUI下测试一下
        {
            HWND hwnd
=GetForegroundWindow();
            HDC hdc
=GetDC(hwnd);
            wostringstream  myString;
          myString
<<"x="<<a<<","<<"y="<<b<<endl;myString.str();
            TextOut(hdc,
0,0,myString.str().c_str(),wcslen(myString.str().c_str()));
            ReleaseDC(hwnd,hdc);
        }
        Math::
~Math(void)
        {
        }
    WinTest_C.def
        LIBRARY    
"WinTest3"
        EXPORTS
        add   @
1
        
?sub@Math@@QAEHHH@Z @2
        
?instance@Math@@SAPAV1@XZ  @3
        
?deleteMath@Math@@SAXPAX@Z @4
        
?output@Math@@QAEXHH@Z @5
    千万别把上面的文件名,类名与方法名以某种联系,其实都是我当时突然想出来做一个测试用的.而文件WinTest_C.def中变形后的方法名是在文件WinTest3.map中找到的,你可以在项目中生成此文件的选项.
然后在C#项目中做一个测试:
Project:WinInterop
    Files:
    NMath.cs
        
using System;
        
using System.Collections.Generic;
        
using System.Text;
        
using System.Runtime.InteropServices;
        
        
namespace WinInterop
        {
          
class NMath
          {
            [DllImport(
"WinTest3.dll", EntryPoint = "?sub@Math@@QAEHHH@Z", CallingConvention = CallingConvention.ThisCall)]
            
public static extern int sub(IntPtr the, int a, int b);
        
            [DllImport(
"WinTest3.dll", EntryPoint = "?instance@Math@@SAPAV1@XZ", CallingConvention = CallingConvention.StdCall)]
            
public static extern IntPtr CreateMath();
        
            [DllImport(
"WinTest3.dll", EntryPoint = "?deleteMath@Math@@SAXPAX@Z", CallingConvention = CallingConvention.StdCall)]
            
public static extern void DeleteMath(IntPtr instance);
        
            [DllImport(
"WinTest3.dll", EntryPoint = "?output@Math@@QAEXHH@Z", CallingConvention = CallingConvention.ThisCall)]
            
public static extern void output(IntPtr instance, int a, int b);
          }
        }
    Form1部分:
            
private void button1_Click(object sender, EventArgs e)
            {
              IntPtr instance 
=NMath.CreateMath();
              NMath.output(instance, 
1010);
              NMath.DeleteMath(instance);
                  }
            这一个测试成功,界面上能看到输出的结果.

 看到上面这一段代码后,相信很多的朋友都会觉得很别扭,觉得真正实现当中怎么可能用这一种方法.首先说为什么我会用Math* Math::instance()这一种方法来生成类吧.因为在C#项目中,我不知道如何externMath的构造方法去生成类.对应的void Math::deleteMath(void * m) 也是一样的原因啦.然后说到WinTest_C.def的方法名,里面很多变异后的方法名是在.map文件当中找到的,并且你每添加一个方法都得重新生成并找出来,添加到.def文件当中,如果你想修改方法名的话更加烦麻.然后还有NMath里面那么多的static,entrypoint.这不是一个开发人员应该用的方法,代码写得多,没有结构,并且都还是做一些低级的开发工作,如查找无聊的方法名,当时就对这一种方法脑火了.

         上一个方法失败后开始想到IDispatch,IUnKnown等COM技术.但又不想自己全部去实现所有的这一些接口,然后想到用ATL项目开发.这样便开始走入正轨.关于COM的细节与ATL的一些知识我这里不能多说,水平也没达到,但我可以说一下我是如何使用ATL一步步实现我预期的方案的.

版权声明:本文为博主http://www.zuiniusn.com 原创文章,未经博主允许不得转载。

Interop(交互) Between C# and C++ 研究一

标签:动态规划   android   

原文地址:http://blog.csdn.net/u013141940/article/details/46803273

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!