que otro librerias lenguaje incluir headers encabezados ejemplos definicion cabecera archivos archivo c# c++ header c-preprocessor versioning

c# - librerias - incluir un archivo c en otro



Reutilizar declaración de definición del archivo.h en el código C# (7)

MSDN nos dice:

La directiva #define no se puede usar para declarar valores constantes, como suele hacerse en C y C ++. Las constantes en C # se definen mejor como miembros estáticos de una clase o estructura. Si tiene varias constantes, considere crear una clase separada de "Constantes" para contenerlas.

Puede crear una biblioteca utilizando C ++ administrado que incluya un contenedor de clase alrededor de sus constantes. Entonces puede hacer referencia a esta clase desde el proyecto C #. Simplemente no olvides usar readonly <tipo> en lugar de const <tipo> para tu declaración de constantes :)

Tengo un proyecto de C ++ (VS2005) que incluye un archivo de encabezado con el número de versión en la directiva #define. Ahora necesito incluir exactamente el mismo número en el proyecto gemelo de C #. ¿Cuál es la mejor manera de hacerlo?

Estoy pensando en incluir este archivo como un recurso, luego analizarlo en tiempo de ejecución con regex para recuperar el número de versión, pero tal vez haya una mejor manera, ¿qué opinas?

No puedo mover la versión fuera del archivo .h, también el sistema de compilación depende de él y el proyecto de C # debe adaptarse.


Puede escribir la utilidad simple de C ++ / C que incluye este archivo .h y crear dinámicamente el archivo que se puede usar en C #.
Esta utilidad se puede ejecutar como parte del proyecto C # como una etapa de preconstrucción.
De esta manera, siempre estará sincronizado con el archivo original.


Puede lograr lo que quiere en solo unos pocos pasos:

  1. Crear una tarea MSBuild - http://msdn.microsoft.com/en-us/library/t9883dzc.aspx
  2. Actualice el archivo de proyecto para incluir una llamada a la tarea creada antes de la compilación

La tarea recibe un parámetro con la ubicación del archivo .h de encabezado que ha recomendado. A continuación, extrae la versión y la coloca en un archivo de marcador de posición C # que haya creado previamente. O puede pensar en usar AssemblyInfo.cs que normalmente contiene versiones si eso está bien para usted.

Si necesita información adicional, no dude en comentar.


Escribí un script de Python que convierte #define FOO "bar" en algo utilizable en C # y lo estoy usando en un paso previo a la construcción en mi proyecto C #. Funciona.

# translate the #defines in messages.h file into consts in MessagesDotH.cs import re import os import stat def convert_h_to_cs(fin, fout): for line in fin: m = re.match(r"^#define (.*) /"(.*)/"", line) if m != None: if m.group() != None: fout.write( "public const string " / + m.group(1) / + " = /"" / + m.group(2) / + "/";/n" ) if re.match(r"^//", line) != None: fout.write(line) fin = open (''../common_cpp/messages.h'') fout = open (''../user_setup/MessagesDotH.cs.tmp'',''w'') fout.write( ''using System;/n'' ) fout.write( ''namespace xrisk { class MessagesDotH {/n'' ) convert_h_to_cs(fin, fout) fout.write( ''}}'' ) fout.close() s1 = open(''../user_setup/MessagesDotH.cs.tmp'').read() s2 = open(''../user_setup/MessagesDotH.cs'').read() if s1 != s2: os.chmod(''../user_setup/MessagesDotH.cs'', stat.S_IWRITE) print ''deleting old MessagesDotH.cs'' os.remove(''../user_setup/MessagesDotH.cs'') print ''remaming tmp to MessagesDotH.cs'' os.rename(''../user_setup/MessagesDotH.cs.tmp'',''../user_setup/MessagesDotH.cs'') else: print ''no differences. using same MessagesDotH.cs''


Consideraría usar un archivo .tt para procesar .h y convertirlo en un archivo .cs. Es muy fácil y los archivos fuente serán parte de su solución C # (lo que significa que se actualizarán a medida que el archivo .h cambie), se puede hacer clic para abrir en el editor, etc.

Si solo tienes 1 #define, podría ser un poco exagerado, pero si tienes un archivo lleno de ellos (por ejemplo, un archivo mfc resource.h quizás), esta solución se convierte en una gran ganancia.

por ejemplo: crea un archivo, DefineConverter.tt y agrégalo a tu proyecto, cambia la línea marcada para referirte a tu archivo .h, y obtendrás una nueva clase en tu proyecto llena de entradas estáticas const. (tenga en cuenta que el archivo de entrada es relativo a su archivo de proyecto, establezca hostspecific = false si desea rutas absolutas).

<#@ template language="C#v3.5" hostspecific="True" debug="True" #> <#@ output extension="cs" #> <#@ assembly name="System.Core.dll" #> <#@ import namespace="System" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.IO" #> <# string input_file = this.Host.ResolvePath("resource.h"); <---- change this StreamReader defines = new StreamReader(input_file); #> //------------------------------------------------------------------------------ // This code was generated by template for T4 // Generated at <#=DateTime.Now#> //------------------------------------------------------------------------------ namespace Constants { public class <#=System.IO.Path.GetFileNameWithoutExtension(input_file)#> { <# // constants definitions while (defines.Peek() >= 0) { string def = defines.ReadLine(); string[] parts; if (def.Length > 3 && def.StartsWith("#define")) { parts = def.Split(null as char[], StringSplitOptions.RemoveEmptyEntries); try { Int32 numval = Convert.ToInt32(parts[2]); #> public static const int <#=parts[1]#> = <#=parts[2]#>; <# } catch (FormatException e) { #> public static const string <#=parts[1]#> = "<#=parts[2]#>"; <# } } } #> } }


Siempre puede usar el evento de preconstrucción para ejecutar el preprocesador C en el archivo .cs y el evento de compilación posterior para deshacer el paso de preconstrucción. El preprocesador es solo un sistema de sustitución de texto, por lo que es posible:

// version header file #define Version "1.01" // C# code #include "version.h" // somewhere in a class string version = Version;

y el preprocesador generará:

// C# code // somewhere in a class string version = "1.01";


Basándome en la solución de gbjbaanb, creé un archivo .tt que busca todos los archivos .h en un directorio específico y los transfiere a un archivo .cs con múltiples clases.

Diferencias

  • Agregué soporte para dobles
  • Cambiado de try-catch a TryParse
  • Lee múltiples archivos .h
  • Utiliza ''readonly'' en lugar de ''const''
  • Recorta # definir líneas que terminan en ;
  • El espacio de nombre se establece en base a la ubicación .tt en el proyecto

<#@ template language="C#" hostspecific="True" debug="True" #> <#@ output extension="cs" #> <#@ assembly name="System.Core.dll" #> <#@ import namespace="System" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.IO" #> <# string hPath = Host.ResolveAssemblyReference("$(ProjectDir)") + "ProgramData//DeltaTau//"; string[] hFiles = System.IO.Directory.GetFiles(hPath, "*.h", System.IO.SearchOption.AllDirectories); var namespaceName = System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint"); #> //------------------------------------------------------------------------------ // This code was generated by template for T4 // Generated at <#=DateTime.Now#> //------------------------------------------------------------------------------ namespace <#=namespaceName#> { <#foreach (string input_file in hFiles) { StreamReader defines = new StreamReader(input_file); #> public class <#=System.IO.Path.GetFileNameWithoutExtension(input_file)#> { <# // constants definitions while (defines.Peek() >= 0) { string def = defines.ReadLine(); string[] parts; if (def.Length > 3 && def.StartsWith("#define")) { def = def.TrimEnd('';''); parts = def.Split(null as char[], StringSplitOptions.RemoveEmptyEntries); Int32 intVal; double dblVal; if (Int32.TryParse(parts[2], out intVal)) { #> public static readonly int <#=parts[1]#> = <#=parts[2]#>; <# } else if (Double.TryParse(parts[2], out dblVal)) { #> public static readonly double <#=parts[1]#> = <#=parts[2]#>; <# } else { #> public static readonly string <#=parts[1]#> = "<#=parts[2]#>"; <# } } } #> } <#}#> }