更新接受了Ira Baxter的回答,因为它指出了我正确的方向:我首先通过开始编译阶段的实现来弄清楚我实际需要什么,很明显很快,节点内的遍历使得这是一个不可能的方法.并非所有节点都应该被访问,其中一些节点的顺序相反(例如,首先是赋值的rhs,因此编译器可以检查类型是否与rhs /运算符匹配).在访问者中进行遍历使得这一切变得非常简单.
在决定对应用程序中使用的迷你语言的处理进行重大修改之前,我正在玩AST和类似的东西.我已经构建了一个Lexer/Parser,可以让AST很好.还有一个访问者,作为具体实现,我创建了一个ASTToOriginal,它只是重新创建原始源文件.最终,还有一些编译器也可以实现Vsisitor并在运行时创建实际的C++代码,所以我想确保一切从一开始就是正确的.虽然现在一切正常,但由于遍历顺序在访问者本身中实现,因此存在一些相似/重复的代码.
在查找更多信息时,似乎某些实现更喜欢在访问对象本身中保留遍历顺序,以便不在每个具体访问者中重复此操作.即便是GoF也只是以同样的方式对此进行了简要的讨论.所以我想尝试这种方法,但很快就陷入了困境.让我解释一下.
示例源代码行和相应的AST节点:
if(t>100?x=1;sety(20,true):x=2)
Conditional
BinaryOp
left=Variable [name=t], operator=[>], right=Integer [value=100]
IfTrue
Assignment
left=Variable [name=x], operator=[=], right=Integer [value=1]
Method
MethodName [name=sety], Arguments( Integer [value=20], Boolean [value=true] )
IfFalse
Assignment
left=Variable [name=x], operator=[=], right=Integer [value=1]
Run Code Online (Sandbox Code Playgroud)
一些代码:
class BinaryOp {
void Accept( Visitor* v ){ v->Visit( this ); }
Expr* left;
Op* op;
Expr* right;
};
class Variable {
void Accept( Visitor* v ){ v->Visit( this ); }
Name* name;
};
class Visitor { //provide basic traversal, terminal …
Run Code Online (Sandbox Code Playgroud) 考虑以下代码:
#include <memory.h>
#include <stdlib.h>
void Foo()
{
const char ** caps = malloc( sizeof( char * ) );
memset( caps, 0, sizeof( char * ) );
}
Run Code Online (Sandbox Code Playgroud)
使用gcc 4.9.2 -pedantic编译精细但是cl 18(来自VS2013的那个)warning C4090: 'function' : different 'const' qualifiers
在memset行上显示默认选项.
现在caps
是一个指向const char指针的指针?所以指针本身不是const因此它应该转换为void*
没有问题,我认为,但cl似乎自动const void*
从它生成警告.这是对正在发生的事情的正确解释吗?这是非标准行为,对吧?
我有一种语言与C++类似的语法.词法分析器和解析器就位并产生正确的AST.对于最大的部分,后端也已完成.
编译器用于创建类型的基本系统非常简单:所有类型都被认为是内置的,所有实例都是全局的.因此,只有一个简单的映射,它将类型名称与创建变量的方法相匹配,该变量基本上是一个泛型类型,如boost :: any.另一个变量名称为key且Variable为value的映射用作全局范围:
std::map< std::string, std::function< Variable() > typeList;
//register some types
typeList[ "X" ] = Variable::Create<X>;
typeList[ "Y" ] = CreateInstanceOfY;
....
Run Code Online (Sandbox Code Playgroud)
当编译器获得AST节点进行初始化时就像X myVar;
它基本上一样
std::map< std::string, Variable > globalScope;
globalScope[ "myVar" ] = typeList[ "X" ]();
Run Code Online (Sandbox Code Playgroud)
当稍后使用myVar时,可以通过简单的类型调度来访问它
X& x = myVar.GetReference<X>();
Run Code Online (Sandbox Code Playgroud)
现在我想扩展一下并使用简单的模板.假设存在使用向量实现的类型"数组".我可以注册一切像
typeList[ "array<X>" ] = Variable::Create< std::vector< X > >;
Run Code Online (Sandbox Code Playgroud)
但这不是很可管理的,因为它必须对所有组合重复.理想情况下,我需要功能允许写这样的东西:
typeList.CreateTemplateVariable( "array", "X" )
Run Code Online (Sandbox Code Playgroud)
然后会创建一个内部包含std :: vector <X>的Variable实例.我努力了,但无法弄清楚如何做到这一点.也许我只是用简单的类型映射开始了错误的方式,这就是我无法理解它的原因.
所以问题很简单:是否可以这样做?如何?
我有一个a.exe
运行良好的应用程序并加载了一个程序集b.dll
,如果重要的话,这是一个Prism模块.此dll是从不在路径中但a.exe
位于所在目录中的目录加载的.
装配由Prism完成,并设置如下:
public class MyModuleCatalog : ComposablePartCatalog
{
private readonly AggregateCatalog _catalog;
public MyModuleCatalog()
{
//directory Modules is not in the path, but all
//dependencies of b.dll are, so b.dll gets loaded fine
var asmCat = new AssemblyCatalog( "Modules/b.dll" );
_catalog.Catalogs.Add( asmCat );
}
public override IQueryable<ComposablePartDefinition> Parts
{
get { return _catalog.Parts; }
}
}
class BootStrapper : MefBootstrapper
{
....
protected override void ConfigureAggregateCatalog()
{
base.ConfigureAggregateCatalog();
AggregateCatalog.Catalogs.Add( new AssemblyCatalog( Assembly.GetExecutingAssembly() ) ); …
Run Code Online (Sandbox Code Playgroud) 我正在使用Msbuild来编译和生成.zip文件和安装程序,我需要我的assembyInfo的版本号.
我正在使用此代码.
<Target Name="getversion">
<GetAssemblyIdentity AssemblyFiles="$(BuildDir)\myprogram.exe">
<Output TaskParameter="Assemblies" ItemName="fooAssemblyInfo"/>
</GetAssemblyIdentity>
<Message Text="Version = %(fooAssemblyInfo.Version)"/>
</Target>
Run Code Online (Sandbox Code Playgroud)
但这会返回Version = 2.0.0.29110,我只需要次要和主要版本.
有没有办法在没有自定义任务的情况下读取assembyInfo.cs信息?
我目前有一个没有扩展的VS安装,看看它是如何工作的.对于导航意味着大量使用Ctrl+;
aka Search Solution Explorer
.虽然搜索本身还可以,但它对我来说有一个主要的缺点,这对我来说很麻烦(使用键盘和鼠标):
两个项目的解决方案,一个折叠,一个打开:
使用Ctrl+;
并开始键入,直到从折叠项目中找到匹配项
我现在想要的是简单地清除搜索并返回上一个视图.看起来像一个非常标准的要求,不是吗?但似乎没有内置这样的功能.当前命令的问题(解决方案资源管理器工具栏中的按下Esc
,单击Back
或Home
按钮)都是一样的:他们有非常讨厌的行为,他们坚持突然贬低先前崩溃项目并跟踪找到的匹配!(顺便提一下Track Active Item in Solution Explorer
选项中的选项).从UX的角度来看,这没有任何意义吗?你选择某种'撤消'命令,搜索框清除预期的,但突然之间有一个项目从前一个搜索可见:
因此,如果折叠的项目中有50个项目,那么解决方案资源管理器在视觉上是无用的,因为它会在屏幕上显示您不想看到的内容,更糟糕的是您必须再次手动折叠项目以返回到上一个视图.
有没有解决的办法?我想Back/Home的键盘快捷键可能会有所不同,但命令似乎没有注册.我调查过,EnvDTE80.DTE2.ToolWindows.SolutionExplorer
但它没有与此问题有关的属性/方法.在树的某个地方有一个Microsoft.VisualStudio.PlatformUI.SolutionPivotNavigator
可能是负责此行为的类,但我不知道如何访问它?
我试着像这样编写一个简单的Qt应用程序:
main.cpp:
#include <QApplication>
class MyApp : public QApplication {
Q_OBJECT
public:
MyApp(int argc, char* argv[]);
};
MyApp::MyApp(int argc, char* argv[]) :
QApplication(argc,argv) {
}
int main(int argc, char* argv[]) {
MyApp app(argc,argv);
return app.exec();
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试编译并将其与Qt Creator 2.3.1(Qt 4.7.4)链接时,我得到3个"未解析的外部符号"错误:
main.obj:-1:错误:LNK2001:未解析的外部符号
""public:virtual struct QMetaObject const*__thiscall MyApp :: metaObject(void)const"
(?metaObject @ MyApp @@ UBEPBUQMetaObject @@ XZ)".
main.obj:-1:错误:LNK2001:未解析的外部符号
""public:virtual void*__thiscall MyApp :: qt_metacast(char const*)"
(?qt_metacast @ MyApp @@ UAEPAXPBD @ Z)".
main.obj:-1:错误:LNK2001:未解析的外部符号
""public:virtual int __thiscall MyApp :: qt_metacall(enum QMetaObject :: Call,int,void**)" …
我在命令行上使用msbuild来构建包含C++项目的VS2012解决方案.该项目有一个在构建之后运行的目标:
<Target Name="RunTargetAfterBuild" AfterTargets="Build">
<Error Text="I am a failing target" />
</Target>
Run Code Online (Sandbox Code Playgroud)
我希望msbuild在构建时返回错误,但是在构建过程中的某个地方,错误会丢失并且msbuild报告"构建成功".因此,ERRORLEVEL仍然设置为0,因此在自动构建期间检测是否出现问题非常困难.如何让msbuild将此错误一直传播到顶级项目/解决方案?我知道这是可能的,因为编译器错误等会发生这种情况.
以下是输出的相关部分:
> msbuild test.sln
...
...: error : I am a failing target [...test.vcxproj]
Done Building Project "...test.vcxproj" (default targets) -- FAILED.
Done Building Project "...test.vcxproj.metaproj" (default targets).
Done Building Project "...test.sln" (Build target(s)).
Build succeeded. --> this is NOT what I want
....
0 Warning(s)
1 Error(s)
Run Code Online (Sandbox Code Playgroud)
对于编译器错误,输出是这样的:
> msbuild test.sln
....
...: error C3861: 'HECK': identifier not found [...test.vcxproj]
Done Building Project "...test.vcxproj" (default targets) …
Run Code Online (Sandbox Code Playgroud) 我们有一个针对DirextX 7 SDK编程的软件(即代码使用 LPDIRECTDRAWSURFACE7
等)并全屏运行.主要任务是以可靠的方式在屏幕上放置一些内容以响应外部触发器.这在Windows XP上表现得非常好:通常软件会等待一些触发器,当触发时,会创建一个新帧,将其放入后备缓冲区,然后告诉DX翻转缓冲区.结果是触发器和屏幕上有效显示帧之间的近似延迟,取决于视频卡和驱动程序,对于60Hz屏幕,3帧或50毫秒.这是在各种系统上测试的,都运行NVidia卡.在一些具有较高端卡的系统上,我们甚至可以获得2帧.
但是,在Windows 7上运行相同的软件时(根本没有安装其他软件),我们不能低于5帧.在管道中的某个地方,操作系统或驱动程序或两者都需要2个额外的帧,这几乎是应用程序无法接受的.我们尝试禁用航空/桌面组合/不同的驱动程序版本/不同的视频卡但无济于事.
在这里编辑一些似乎相关的代码:
创建前/后表面:
ddraw7->SetCooperativeLevel( GetSafeHwnd(),
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_MULTITHREADED )
DDSURFACEDESC2 desc;
ZeroMemory( &desc, sizeof(desc) );
desc.dwSize = sizeof( desc );
desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE |
DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
desc.dwBackBufferCount = 1;
ddraw7->CreateSurface( &desc, &primsurf, 0 )
DDSCAPS2 surfcaps;
ZeroMemory( &surfcaps,sizeof( surfcaps ) );
surfcaps.dwCaps = DDSCAPS_BACKBUFFER;
primsurf->GetAttachedSurface( &surfcaps, &backsurf );
Run Code Online (Sandbox Code Playgroud)
创建用于在绘制帧之前渲染帧的曲面:
DDSURFACEDESC2 desc;
ZeroMemory( …
Run Code Online (Sandbox Code Playgroud) 我使用的代码这样做在WPF应用程序屏幕截图。简而言之:
var drawingvisual = new DrawingVisual();
using( DrawingContext context = drawingvisual.RenderOpen() )
{
context.DrawRectangle( new VisualBrush( fooElement ), null, new Rect( fooElementSize ) );
context.Close();
}
var r = new RenderTargetBitmap( ... );
r.Render( drawingvisual );
SaveBitmapToFile( r, .... );
Run Code Online (Sandbox Code Playgroud)
该原理工作得很好,例如在单击鼠标时调用时,但我在以编程方式调用它时遇到了问题。流程是:
Application.Current.Dispatcher.Invoke
Application.Current.Dispatcher.Invoke
这在我的开发机器上工作正常,但在某些用户的机器上,这会导致保存的图像不包含所有更新。因此,例如,当 TextBlock 具有文本“running”并且上面的第一步将其设置为空字符串时,屏幕截图仍显示 TextBlock 的“running”。或者,如果第一步包括用一堆元素填充 Canvas,屏幕截图只是不包括它们。当要渲染的元素隐藏在其他窗口等后面时,情况也会变得更糟。
考虑到这一点,似乎关键问题是 WPF 使用单独的渲染线程,并且只有当该线程完成其工作时,UI 才会真正绘制并准备好捕获。四处搜索会产生一些点击,甚至一些“解决方案”围绕......
Application.Current.Dispatcher.BeginInvoke( DispatcherPriority.ApplicationIdle,
new Action( () => { } ) ).Wait();
Run Code Online (Sandbox Code Playgroud)
...但据我所知,这只是等到 UI 线程空闲,这并不能保证渲染线程已完成更新我想要捕获的 UI 部分?无论如何,在捕获代码之前在后台线程中插入这一行没有任何区别。有时似乎有效的方法只是将后台线程阻塞 100 …
c++ ×3
c# ×2
msbuild ×2
.net ×1
assemblyinfo ×1
c ×1
c++11 ×1
directx ×1
gcc ×1
latency ×1
moc ×1
nvidia ×1
pointers ×1
prism ×1
qt ×1
qt-creator ×1
qt4 ×1
screenshot ×1
system.type ×1
visitor ×1
visual-c++ ×1
windows-7 ×1
wpf ×1