平台移植 - 4 (Cygwin与Win32程序的交互)
来源:互联网 发布:vb.net打开指定文件夹 编辑:程序博客网 时间:2024/05/11 21:20
http://blog.csdn.net/null_shadow/article/details/1807797
前面几章谈到了Cygwin的安装, 培植, 编译, 运行 等基本步骤, 本章将要讨论整个平台代码移植中的重点 : 程序的交互. (Cygwin <-> Win32)
根据调用的方式, 我把交互简单分为下面2类:
1. Cygwin程序调用Win32-Function :
据前所述, Cygwin平台下是架构在Win32平台上的一个子平台, 所以其本身就有调用Win32-API的能力.(可以用VC6提供的Dependency-Walker打开/bin/cygwin1.dll查看,会发现其主要依赖于KERNEL32.dll), 所以在Cygwin里面, 如果想调用Win32-API如 : MessageBoxA(...), 只需要在Source里简单的include <windows.h> 再调用就可以了, 用Cygwin-GCC编译测试, 可以看到程序正常运行.
所以, Cygwin调用Win32程序没有太大的困难, 至少知道是有途径可以调用成功的.
2. Win32程序调用Cygwin-Function :
Cygwin官方并不提供这种直接的Win32调用Cygwin-DLL里面Function的能力. 原因大致是: 依赖于Cygwin平台的程序在入口的时候(特别的, 是在main-function执行之前),需要由Cygwin进行必要的Init. 如果是以Win32程序作为入口点, 则没办法由Cygwin平台直接提供这样的支持.(因为Cygwin只提供基于Cygwin平台的编译器)
不过,非官方的提供了这样的途径用于Win32-EXE调用Cygwin-DLL. 方法有静态调用和动态调用两种之分.
下面主要介绍的是动态调用 (很遗憾, 静态调用没有测试成功, 有调用成功的朋友敬请提出解决方案:)~)
动态调用的过程大致如下:
1.Make sure you have 4K of scratch space at the bottom of your stack.
-- Do this before or just at your program starting.
2.Dynamic - loading Cygwin1.dll, and call the method : "cygwin_dll_init" to do the Init. work.
3.Dynamic - loading the function u wanna in Cygwin-DLL.
即确保你的堆栈底部有大约4K的空间 (其实是Cywin里面有个叫cygtls的结构体决定的, 一般不会超过4KB). 这4KB空间即是Cygwin平台运行时,其做一些操作所需要的一个空间, 所以必须确保这块空间留给Cywin, 而不是应用程序本身. 然后, 动态调用Cygwin1.dll里面的cygwin_dll_init方法做初始化动作. 到此, 初始化的动作就全部完成了. 接下来, 就可以动态调用任意你想要的在Cygwin-DLL里面的Function了.
在实现方法上, 由Max Kaehn提供了一种简单的方法实现. (见下面的参考链接-2)
主要的代码贴在这里: (由Max Kaehn提供, 再由我的一位同事XiaoHu精简改写 ^_^ ~~)
padding.cpp :
#include <stdio.h>
#include <iostream>
#include <vector>
#include "padding.h"
using std::cout;
using std::cerr;
using std::endl;
padding *padding::_main = NULL;
DWORD padding::_mainTID = 0;
padding::padding ()
{
_main = this;
_mainTID = GetCurrentThreadId ();
_end = _padding + sizeof (_padding);
char *stackbase;
#ifdef __GNUC__
__asm__ (
"movl %%fs:4, %0"
:"=r"(stackbase)
);
#else
__asm
{
mov eax, fs:[4];
mov stackbase, eax;
}
#endif
_stackbase = stackbase;
// We've gotten as close as we can to the top of the stack. Even
// subverting the entry point, though, still doesn't get us there-- I'm
// getting 64 bytes in use before the entry point. So we back up the data
// there and restore it when the destructor is called:
if ((_stackbase - _end) != 0)
{
size_t delta = (_stackbase - _end);
_backup.resize (delta);
memcpy (&(_backup[0]), _end, delta);
}
}
padding::~padding ()
{
_main = NULL;
if (_backup.size ())
{
memcpy (_end, &(_backup[0]), _backup.size ());
}
}
void padding::check ()
{
if (_main == NULL)
throw std::runtime_error ("No padding declared!");
if (_mainTID != GetCurrentThreadId ())
throw std::runtime_error ("You need to initialize cygwin::connector "
"in the same thread in which you declared the "
"padding.");
if (_main->_backup.size ())
cout << "Warning! Stack base is "
<< static_cast<void *>(_main->_stackbase)
<< ". padding ends at " << static_cast<void *>(_main->_end)
<< ". Delta is " << (_main->_stackbase - _main->_end)
<< ". Stack variables could be overwritten!" << endl;
}
cygload.cpp :
#include <stdio.h>
#include <vector>
#include "padding.h"
HMODULE hModule = NULL;
void InitCygwin()
{
if(hModule == NULL)
{
hModule = LoadLibrary(TEXT("cygwin1.dll"));
void (*cygwin_dll_init)() =(void (*)())GetProcAddress(hModule, "cygwin_dll_init");
cygwin_dll_init();
}
}
void FreeCygwin()
{
if(hModule != NULL)
{
FreeLibrary(hModule);
hModule = NULL;
}
}
extern "C" void CygwinStartUp(void (*main)())
{
padding padding;
InitCygwin();
main();
FreeCygwin();
}
将上面的代码用VS.NET编译成CygLoad.dll.
下面是Main-Function开始时调用的代码(用VB.NET编写)
Friend Class Program
' Nested Types
Public Delegate Sub MainEntryMethod()
' Methods
<DllImport("CygLoad.dll")> _
Public Shared Sub CygwinStartUp(ByVal mainEntry As MainEntryMethod)
End Sub
<STAThread()> _
Friend Shared Sub Main()
Program.CygwinStartUp(New Program.MainEntryMethod(AddressOf Program.MainEntry))
End Sub
Friend Shared Sub MainEntry()
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(New MainForm())
End Sub
End Class
上面的代码即是做初始化工作, 完成后, 就可以在你的代码的任意地方动态调用function了, 如下:
{
void (*lpFunctionInCygwin)(char*);
HMODULE hExport = LoadLibrary(TEXT("FunctionInCygwin.dll")); //Cygwin编译的实际的DLL
lpFunctionInCygwin= (void(*)(char*))GetProcAddress(hExport,"FunctionInCygwin");
lpFunctionInCygwin(str); //动态调用该DLL里面的FunctionInCygwin方法.
FreeLibrary(hExport);
}
到此调用全部Over. 在你的代码里面直接调用FunctioninCygwin即可(实际上是动态调用Cygwin编译的FunctionInCygwin.dll 里面的 FunctionInCygwin(char *) 方法.
参考:
http://cygwin.com/faq/faq.programming.html#faq.programming.msvs-mingw
http://cygwin.com/ml/cygwin-patches/2005-q2/msg00102.html
- 平台移植 - 4 (Cygwin与Win32程序的交互)
- Cocos2dx之使用cygwin移植win32项目到Android平台
- Cygwin: 一个自由的、UNIX应用程序的Win32移植层
- win7下把win32游戏移植到Android平台(无需cygwin和minigw)
- 使用cygwin编译win32程序
- cocos2d-x入门(7)-win7下把win32游戏移植到Android平台(无需cygwin和minigw)
- cocos2d-x入门(7)-win7下把win32游戏移植到Android平台(无需cygwin和minigw)
- ubuntu 与 hisi平台 程序移植
- cocos2d-x 笔记(一) win32环境配置以及eclipse+ndk+sdk+cygwin的android移植
- win32环境配置以及eclipse+ndk+sdk+cygwin的android移植
- cygwin移植linux程序到windows及在eclipse中使用cygwin的常见问题
- cygwin与漏洞攻击程序的编译
- WinCE平台的程序编译到Win32平台下运行
- WinCE平台的程序编译到Win32平台下运行
- WinCE平台的程序编译到Win32平台下运行
- cocos2dx—win32平台打包成akp的方法,无需安装cygwin
- J2ME程序的平台移植办法
- cygwin跨平台移植 gcc+vc联合使用的方法和注意事项
- GCC—C程序是如何编译成的 -windows
- 送给“苦逼”的IT人系列4:关于voice out以及on the table
- 在Windows操作系统下的gcc
- ubuntu12.04 编译 ics android 4.0.4 日志 ,出出错
- 【每日听力活动训练】第十三期 0406
- 平台移植 - 4 (Cygwin与Win32程序的交互)
- Form Level Debug (FRD Debug Small Tips)
- php循环一边执行一边输出
- android之Uri的常用几个例子
- Socket经验记录
- java与c++中的对象序列化 分析。
- java/继承
- Reuters:Facebook将进军电子商务界
- Jquery旋转动画实现