注册 登录
编程论坛 VC++/MFC

在 VS 下调用 MinGW 做个自己的编译器 IDE,该方案是否可行?

cr945211 发布于 2014-08-24 10:09, 2537 次点击
搞了快两个月了,还没有头绪,现在就想问一下各路大神,这个方案可行吗?
   由于我们要在VS下做一个自己的图形编程IDE,我负责编译器这块,也就是说,通过图形编程生成的程序可以在我这里编译、运行和调试。。最初的方案就定了调用外部编译器MinGW来做成大家常见的IDE。。但是现在找不到解决方法,在本论坛也发过帖子问问题,但貌似都没有解决到点子上。。请问大神们有没有这方面的经验?小弟真实捉急啊,拜托  (分数不多,但是我把全部分都押上了,希望大家帮忙)
21 回复
#2
cr9452112014-08-24 10:25
由于MinGW是CMD窗口下用命令行操作的,所以,刚开始便采用匿名通道向cmd.exe发送命令执行,返回结果的方法。但是,现在的问题是,当给CMD发送一个命令后,它执行完就关闭了,但是MinGW里面的命令上下都有关联啊,所以就采用了双通道,输入通道和输出通道,用消息响应的方式(就像常见的IDE里面那些按键)关联特定的命令行,输入到通道中……我是这样想的,感觉会实现,但是现在就卡在这里了。。所以,这种方法到底能实现吗?是不是需要自己写一个控制台程序啊?用系统的CMD能完成吗?
#3
天使梦魔2014-08-25 10:16
本来mingw就是可以纯cmd编译东西的,传说中某些linux疯子在没有外壳下就是这样做的,vs的编译器也可以。
mingw的编译核心是C语言的gcc,C++的g++。然后配上一些语法检查,模块编译之类的东东。
devc++ 就是用Delphi语言开发的,核心使用mingw

你没必要使用vs的编译器ui去配mingw的核心,ui可以自己写
mingw官网上有关于开发ui的说明。(就是如何配置和使用那些核心文件)
然后你可以自己写一个ui界面
#4
zklhp2014-08-25 10:17
C-Free不就是在Win下做了一个界面 编译器是MinGW
#5
天使梦魔2014-08-25 10:24
code::blocks 也是,现在code::blocks好评率已经超过mingw原装编译器。
自己去mingw下载不带gui的套件吧,可以下载最新版本的,至于如何CMD返回。你在程序里不要用cmd去做,而是直接shellexecute
#6
cr9452112014-08-25 15:31
回复 3 楼 天使梦魔
不过我的ui必须得用VS写,因为这一块只是项目的一部分,整个的环境需要用VS
#7
cr9452112014-08-25 15:37
回复 5 楼 天使梦魔
你说的不带GUI的MinGW套件,应该装好了,现在在CMD中可以编译、调试程序。。我用的是CreatProcess(),匿名管道,但不是太会用
#8
cr9452112014-08-25 15:39
回复 4 楼 zklhp
我必须要在VS环境中做
#9
天使梦魔2014-08-25 18:34
对啊,就是用VS开发gui,调用编译核心是你自己写的。
参数和命令参见官网,EXE程序挂参就可以了,互相关系也要参见官网,包括编译顺序。
说白了就是vs写个类似mfc的界面,里面带有启动其它程序的代码。
你必须把mingw了解透,才能制作,也必须做出好的应用。

cmd管道可以搜索找,有函数名可以直接上msdn。能得到回馈信息就已经完成了,剩下的是你gui和mingw参数功底。你得自己学了,这个通不过那后面更难,毕竟写个好点的编译器不是那么随便
#10
cr9452112014-08-25 22:17
回复 9 楼 天使梦魔
mingw的参数已经搞清楚了,现在就是向cmd发命令的问题没解决
#11
天使梦魔2014-08-25 23:28
我去。。。。挂参数啊。那几个编译是接受参数的。
无式和函数启动exe,在xxx.exe后面空格然后加参数。用管道传回所得信息。

16位main有2个,32位winmain有4个。你可以自己写程序测试下,你下载的那几个文件都接受传参的,用这个方法最简单,在核心调用什么命令就用参数调用,写到程序的时候用字符串自己组合。

管道通讯的话参考下
http://bbs.



不过我建议你用第个方法测试
#12
cr9452112014-08-26 22:02
回复 11 楼 天使梦魔
不好意思,这两句话我不是太懂 “无式和函数启动exe,在xxx.exe后面空格然后加参数”
                               “16位main有2个,32位winmain有4个。你可以自己写程序测试下”
   可以解释下吗?
#13
天使梦魔2014-08-27 08:31
打错了而已,我意思你测试的时候不要用管道去发送,而是使用参数形式
#14
cr9452112014-08-27 09:30
回复 13 楼 天使梦魔
对,我测试过,输入命令的时候没有用管道,只是输出的时候用管道重定向到VS界面中。但出现的问题是,给它一个命令后,CMD运行一下就关闭了,然后得到了执行结果。但是,我不可能只给它一个命令,需要好多命令(比如调试的时候),而这些命令也是上下关联的,比如输入gdb命令,则进入调试环境,然后才能设断点、调试等等。
    我用CreateProcess()做的,没有用输入管道,只能完成gcc -o helloworld.exe helloworld.c这种一个命令就能完成的操作。

[ 本帖最后由 cr945211 于 2014-8-27 10:06 编辑 ]
#15
天使梦魔2014-08-27 15:56
可以不使用输入管道,但一定要用管道去得到执行结果,这个执行结果不是最后的exe,而是gcc.exe从cmd里返回出的信息.输入管道只是可以用在编译时隐藏过程的.
如果你不去返回信息很难做.意思是"用管道得到cmd执行信息",而不是编译后的结果.
比如你有个程序是
main()
{
  int a=9,b=1;
  cout<<a+b;
}

这个时候通过管道得到cout的部分,也就是显示在cmd上的东西,你不能在程序内部申请一个变量去用=号进行操作.
就好比假设上面是我写的一个程序,输出a+b结果,你再做一个程序在内部申请字符串变量然后启动我的程序,得到我程序的输出信息,这就是管道作用.

gcc/g++ 这种编译核如果你无法用管道去获得回馈信息,而是看编译成功没那也太那个什么了.(当然你可以使用cmd输出成txt保存信息)
我以前下过gcc手册,里面的命令将近100左右,全是各种参数以及说明,不过我删掉了,你在mingw官网也能下载到英文版的手册.(可以百度下gcc手册,有中文版的)
我不太了解你到底哪里不熟悉或者有问题,看法是如何的.
但...做一个编译器真不是轻松的活,这仅仅是开始而已,不然编译器早烂大街了.
#16
cr9452112014-08-27 17:44
回复 15 楼 天使梦魔
你好,谢谢你的耐心回答,发过好多帖子,水平有限,只能这样一步步来啊
比如我这里有个加法程序 add.cpp
程序代码:

using namespace std;
int main()
{
    int a,b,c;
    cout<<"加法计算器:\n"<<endl;
    cout<<"a= "<<endl;
      cin>>a;
    cout<<"b= "<<endl;
       cin>>b;   
    cout<<"结果为:";
        c=a+b;
    cout<<c<<endl;   
    return 0;
}

   我明白你说的问题,这也是我之前想过的。如果将g++ -o add.exe add.cpp发给CMD后,只是在同目录下生成了add.exe文件,只是返回到CMD窗口中的结果,如果现在我再将add.exe命令发给CMD,也只是显示**a= b=,不能像CMD一样可以输入值再执行。。所以,单看这个加法程序的问题,我是不是要再定义一个线程,CreateProcess(),参数写成add.exe,然后输入两个值给该程序,这样可以得到结果吗?还是说要输入gdb add.exe,然后run,然后给a和b的值?
   如果是第二个方法,就会遇到我一直在问的问题,像你所说的,输入管道只是隐藏了过程,但是我现在没有办法做到让所有的命令都是在同一个CMD下进行(在系统CMD下,肯定是先gdb然后才能在<gdb>下run的,也就是说这些命令上下有关联),而是执行完gdb后,如果再给run他肯定就不认得该命令(CMD下没有run这个命令),那如果想进一步调试,也是不可能的。。这个问题困扰我太久了,真的不知道涉及的什么知识。
#17
天使梦魔2014-08-27 19:01
线程和这个没联系啊,如果新线程能做那主线程为什么不能做?
线程只是让一个程序占用cpu两个时间而已,一个线程不影响另一个消息泵堵塞。但并不代表用线程去执行本体外程序就可以共享内存和接口。
第二个方法,为什么要同时运行?如果使用cmd就不停的挂上exe,每条命令都有一个前端运行程序,gui保存设置好路径,每条参数前都带运行程序exe
你说的必须进入gdb然后运行某命令我暂时理解为不支持参数调用。这时候你找管道输入资料,管道输入就是直接以某exe已经打开然后进行操作,如果使用输入就不要用挂参形式了而是程序内可执行的所有命令。格式也以直接打开exe后怎么输入为准
#18
cr9452112014-08-28 22:32
回复 17 楼 天使梦魔
第一个方法我的意思是,之前不是用CreateProess启动的cmd.exe嘛,那现在生成了add.exe,是不是再定义一个CreateProcess启动add.exe,然后传a,b的值。。。。。
  后面你解释的我有点听不懂(我水平有限啊)。“如果使用cmd就不停的挂上exe,每条命令都有一个前端运行程序,gui保存设置好路径,每条参数前都带运行程序exe”这句话的意思,联系我用的MinGW命令,我理解的是:比方说我编译、链接一个C程序,参数为-o,那用到的是gcc.exe,那我给的命令就是“gcc -o ………”,如果编译、链接一个C++程序,参数也是-o,用到的是g++.exe,那我给的命令就是“g++ -o ………”。应该是这样吧。。gui保存设置好路径指的什么啊?
  后面这句话“你说的必须进入gdb然后运行某命令我暂时理解为不支持参数调用。”我给你发了一个在CMD中运行的图片,当输入gdb add.exe 命令后会进入<gdb>下,也就是调试环境中(因为我后期的重点、难点肯定在调试这一块,设置断点、单步什么的,都要在<gdb>下进行),然后我可以输入run等其他调试时用到的命令。。
只有本站会员才能查看附件,请 登录

   
  “这时候你找管道输入资料,管道输入就是直接以某exe已经打开然后进行操作,如果使用输入就不要用挂参形式了而是程序内可执行的所有命令。格式也以直接打开exe后怎么输入为准”这句话真的说到我心坎儿上了,我感觉问题就是在这里,比方说我现在给gdb命令,打开了调试环境,那我以后都要在这个环境下执行命令,是不是说这个时候用管道输入就可以了。比如说以下语句

        si.hStdInput = hStdinRd;//数据输入用的文件句柄
    si.hStdError = hStdoutWr;//数据输出用的文件句柄
    si.hStdOutput = hStdoutWr;//数据输出用的文件句柄

程序代码:

  void COutputWnd::WriteToPipe(LPCTSTR line)
{
   DWORD dwWritten;
   WriteFile( hStdinWr, line, _tcslen(line)*sizeof(TCHAR),
            &dwWritten, NULL );
}

是这个思考方向吗?

[ 本帖最后由 cr945211 于 2014-8-28 22:33 编辑 ]
#19
天使梦魔2014-08-29 09:47
gui是图形用户界面,百度一下就知道了啊,我说的gui指的是你的编译器ui,总的有配置程序吧...

不过你自己做匿名管道,居然连它的概念也不明白?
我没做过,网上抄的:
程序代码:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <stdio.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE hpiperead = NULL , hpipewrite = NULL;
    SECURITY_ATTRIBUTES ai;     //安全属性  
    ai.nLength = sizeof(SECURITY_ATTRIBUTES);
    ai.bInheritHandle = true ;
    ai.lpSecurityDescriptor = NULL ;

 
    if (!CreatePipe(&hpiperead , &hpipewrite , &ai ,0 ))  //创建管道  
    {
        printf("创建匿名管道失败\n");
        return 0;
    }
     
    char com[1024]; //控制命令  
    char buff[255];
    cin>>buff;

 
    strcpy( com , "cmd.exe /c" );
    strcat( com , buff);

 

 
    STARTUPINFO si;
    PROCESS_INFORMATION pi;      
    GetStartupInfo(&si);    //获取当前进程的STARTUPINFO  
    si.cb = sizeof(STARTUPINFO);
    si.hStdError = hpipewrite ;
    si.hStdOutput = hpipewrite ;
    si.wShowWindow = SW_SHOW ;
    si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;

 
    if (!CreateProcess(NULL , com , NULL , NULL , true , NULL,NULL , NULL , &si , &pi)  )      //创建隐藏的CMD进程  
    {
        CloseHandle(hpipewrite);
        CloseHandle(hpiperead) ;
        cout<<"1"<<endl;
        return 0;
    }
    char outbuff[4096];
     
    DWORD byteread;
    while (1)
    {
        memset( outbuff ,'\0' ,4096 );
        if (ReadFile(hpiperead , outbuff , 4095 , &byteread , NULL) == NULL)
        {
            break;
        }
        printf("%s",outbuff);
        memset( outbuff ,'\0' ,4096 );
    }

 
    cout<<endl;

 
    //创建内核对象使用完之后一定记得关闭,有可能会产生内存泄露  

    CloseHandle(hpipewrite);
    CloseHandle(hpiperead) ;
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread) ;

 
    return 0;
}
我的是vs2008, strcpy函数不支持utf8的字符集,如果你也是,自己配置下工程属性,设置里面,把字符集改成未设置就变车管acii码了.
运行之后它就挂接cmd程序了,你可以输入一个cmd命令比如help,然后得到所有帮助列表回馈.
你也可以自己写个程序.比如
int main()
{
  cout<<"test";
}
编译后把这个程序的exe复制到上面一个exe目录下,然后把strcpy指向你这个的exe,编译运行后,随便输入什么然后回车就可以得到回馈了.(网上抄的代码很烂,有bug,不过我没做过匿名管道,所以我就不去深入了)

通过以上,你可以看到,匿名管道链接后可以发送命令和得到回馈,也就是你想要的结果(模拟直接打开exe然后输入).另外奉劝你一句,做线程的时候不要用CreateProess,我从没用过,我只用安全线程beginthreadex,这个函数没有统一的标准,每个编译器对这个函数的用法都不一样,如果你的编译器有提示,你可以看它的函数原型,然后网上找用法

我觉得你离你的目标好像有点愚公移山的感觉
#20
cr9452112014-08-29 10:50
回复 19 楼 天使梦魔
因为我基础太差所以给你的这种感觉吧?
   我倒是满怀希望的,总感觉解决现在这个问题以后就好办了,一点点把那些命令功能加上去就行了吧。以你的了解,有什么办法把“山”搬得快一点吧?或者说,难点在哪里,我得怎么下苦工?
   匿名通道的问题,我是在网上找别人做的例子然后通过分析知道它的作用,所以好多问题都不确定。。
#21
天使梦魔2014-08-29 13:01
那就慢慢来吧,我也没有好的办法。你没发现缺少什么前,你也无法理解原理就算我告诉你。

http://hi.baidu.com/dreamrl/item/f9935bc20990d0e3ee183bd0
我做这个的时候其实并不怎么会mfc这个库,每个按钮,输入框,列表框都是查询它们的成员函数,整个界面以查询手册完成,而不是搜索什么mfc某个控件如何实现。网上好多都扯蛋,瞎抄瞎写。当有成员需求参数和返回都是很奇怪的时候,只有长期自己做过才能理解为什么要这样。



我要大潜水了。。。。。
#22
天使梦魔2014-08-29 13:09
等等,潜水前忘了喊口号:rz出品,必属精品,用用更健康。
还有rz俄罗斯方块已加入豪华套餐,敬请百度搜索
1