Значение RTNLGRP_NEIGH
будет равно 3. Вы можете легко проверить это с помощью следующей программы.
#include <stdio.h>
/* RTnetlink multicast groups */
enum rtnetlink_groups {
RTNLGRP_NONE,
#define RTNLGRP_NONE RTNLGRP_NONE
RTNLGRP_LINK,
#define RTNLGRP_LINK RTNLGRP_LINK
RTNLGRP_NOTIFY,
#define RTNLGRP_NOTIFY RTNLGRP_NOTIFY
RTNLGRP_NEIGH,
#define RTNLGRP_NEIGH RTNLGRP_NEIGH
RTNLGRP_TC,
#define RTNLGRP_TC RTNLGRP_TC
RTNLGRP_IPV4_IFADDR,
#define RTNLGRP_IPV4_IFADDR RTNLGRP_IPV4_IFADDR
/* ... */
#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR
RTNLGRP_PHONET_ROUTE,
#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
int
main()
{
printf("RTNLGRP_NEIGH = %d\n", RTNLGRP_NEIGH);
}
Он выводит это:
RTNLGRP_NEIGH = 3
Поскольку каждый макрос #define
d для своего имени, RTNLGRP_NEIGH
в main
будет заменен на RTNLGRP_NEIGH
. Но так как расширение не является рекурсивным, оно останавливается в этой точке, и программа использует константу enum
, которая является четвертой и поэтому имеет значение 3.
Если вы не знаете, что препроцессор, вы всегда можете скомпилировать с помощью переключателя -E
и посмотреть на предварительно обработанный вывод. Компиляция приведенного выше примера с gcc -E
дает (не отображая 840 строк стандартных заголовков библиотеки #include
d)
# 4 "main.c"
enum rtnetlink_groups {
RTNLGRP_NONE,
RTNLGRP_LINK,
RTNLGRP_NOTIFY,
RTNLGRP_NEIGH,
RTNLGRP_TC,
RTNLGRP_IPV4_IFADDR,
RTNLGRP_PHONET_ROUTE,
__RTNLGRP_MAX
};
int
main()
{
printf("RTNLGRP_NEIGH = %d\n", RTNLGRP_NEIGH);
}
, который, надеюсь, гораздо менее запутанным.
#define
s, смешанные с определением enum
, не влияют на определение enum
. Не имеет значения, где находятся #define
s. Они могли (и, вероятно, должны были) быть размещены до или после определения.
/* RTnetlink multicast groups */
enum rtnetlink_groups {
RTNLGRP_NONE,
RTNLGRP_LINK,
RTNLGRP_NOTIFY,
RTNLGRP_NEIGH,
RTNLGRP_TC,
RTNLGRP_IPV4_IFADDR,
/* ... */
RTNLGRP_PHONET_ROUTE,
__RTNLGRP_MAX
};
#define RTNLGRP_NONE RTNLGRP_NONE
#define RTNLGRP_LINK RTNLGRP_LINK
#define RTNLGRP_NOTIFY RTNLGRP_NOTIFY
#define RTNLGRP_NEIGH RTNLGRP_NEIGH
#define RTNLGRP_TC RTNLGRP_TC
#define RTNLGRP_IPV4_IFADDR RTNLGRP_IPV4_IFADDR
#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR
/* ... */
#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
Причина, по которой они написали этот прошитый код, вероятно, что они хотели реорганизовать старый код с помощью
#define RTNLGRP_NONE 0
#define RTNLGRP_LINK 1
#define RTNLGRP_NOTIFY 2
#define RTNLGRP_NEIGH 3
#define RTNLGRP_TC 4
#define RTNLGRP_IPV4_IFADDR 5
/* ... */
использовать вместо enum
. Но поскольку существующий код может полагаться на то, что идентификаторы являются макросами (например, тестирование #ifdef RTNLGRP_NEIGH
), они хотели бы предоставить макросы с одинаковым значением. Обратите внимание, что этот подход является ошибочным, поскольку препроцессор не знает значения константы, поэтому вы не можете делать такие вещи, как #if RTNLGRP_NEIGH >= 3
, которые вы могли бы, RTNLGRP_NEIGH
были #define
d до 3
буквально. Таким образом, по сути, их подход сочетает в себе недостатки использования макросов (загрязнение именных пространств) с использованием методов enum
s (недоступно во время предварительной обработки).
Возможно, более полезный образец I прежде были #define
константы действительных целых чисел.
enum rtnetlink_groups {
RTNLGRP_NONE
#define RTNLGRP_NONE 0
= RTNLGRP_NONE,
RTNLGRP_LINK
#define RTNLGRP_LINK 1
= RTNLGRP_LINK,
RTNLGRP_NOTIFY
#define RTNLGRP_NOTIFY 2
= RTNLGRP_NOTIFY,
RTNLGRP_NEIGH
#define RTNLGRP_NEIGH 3
= RTNLGRP_NEIGH,
RTNLGRP_TC
#define RTNLGRP_TC 4
= RTNLGRP_TC,
RTNLGRP_IPV4_IFADDR
#define RTNLGRP_IPV4_IFADDR 5
= RTNLGRP_IPV4_IFADDR,
/* ... */
};
, которые будут предварительно обработаны следующим.
enum rtnetlink_groups {
RTNLGRP_NONE
= 0,
RTNLGRP_LINK
= 1,
RTNLGRP_NOTIFY
= 2,
RTNLGRP_NEIGH
= 3,
RTNLGRP_TC
= 4,
RTNLGRP_IPV4_IFADDR
= 5,
};
Обратите внимание, что здесь что #define
s смешиваются с определением enum
, иначе мы получили бы недопустимый код, например 3 = 3,
, а не желаемый RTNLGRP_NEIGH = 3
.
О, и, пожалуйста, не делайте используйте __RTNLGRP_MAX
как идентификатор. Имена, содержащие два смежных подчеркивания или начинающиеся с символа подчеркивания, за которым следует буква верхнего регистра, зарезервированы по стандарту C. Использование их в вашем собственном коде приводит к неопределенному поведению.
С Wix я сделал бы что-то вроде этого:
<DirectoryRef Id="MyDirectory" > <Component Id="MyComponent" Guid="PUT-GUID-HERE" DiskId="1"> <File Id="MyAssembly" Name="MyAssembly.dll" Assembly=".net" KeyPath="yes" Source="MyAssembly.dll" /> </Component> </DirectoryRef>
, Когда Вы используете блок атрибута = ". сеть" для файла в WiX, это создаст записи в таблице MsiAssembly и MsiAssemblyName для этого компонента и отметит его как компонент GAC.
похоже, что gacutil нужно избежать; это не распространяемое приложение. Вместо этого 'надлежащий' способ установить их, кажется, использует MSI, один способ быть WIX, как отправлено CheGueVerra или другим сценарием.
Разве у Вашего производителя установщика нет способа установить блок в GAC? Самостоятельно, я сказал бы GACUTIL:
http://msdn.microsoft.com/en-us/library/ex0ss12c (По сравнению с 80) .aspx
Если Вы не хотите обрабатывать gacutil, наполняют себя, можно всегда создавать проект установки в Visual Studio.
, Но я придерживался бы gacutil сам.
Используйте System.EnterpriseServices.Internal.Publish
GacInstall
метод.
Преимущества: Кажется, внутренний инструмент. Вероятно, делает весь правильный материал.
Недостатки: Как часть установщика, необходимо было бы все еще сделать и запустить приложение, которое называет это (если установщик, который Вы делаете, не является пользовательским приложением, которое делает это так или иначе).
Лучший способ состоит в том, чтобы использовать gacutil -i Library.dll
.
единственная проблема с gacutil состоит в том, что это не находится в ПУТИ по умолчанию системы. Это находится однако в фиксированном месте относительно каталога окон для данной версии.Net Framework. Таким образом, можно использовать следующую командную строку для выполнения его отовсюду:
%SystemRoot%\Microsoft.Net\Framework\v1.1.4322\gacutil -i
пз: просто копирование Вашего блока в c:\windows\assembly не будет работать. Проводник только показывает упрощенное представление папки, которая содержит на самом деле много различных папок для различных видов блоков. Выполнение копии в нем из установщика не инициирует все операции, сделанные проводником на перетаскивании. (записанный здесь, потому что у меня нет достаточной репутации все же для комментария других сообщений).
используйте gacutil.
Преимущества: кажется, всегда работает. Недостатки:
скопируйте непосредственно в %WINDIR %\Assembly.
Преимущество: Простой.
Недостаток: AFAIK, %WINDIR %\Assembly всего происходит , чтобы быть, где это прямо сейчас, и это - местоположение, подвержен изменениям. Это заставило бы его прервать будущие версии окон или если поведение той папки chaneges. Это, вероятно, не правильный путь.
Экстремальный Недостаток: Как сказано madmath:
просто копирование Вашего блока в c:\windows\assembly не будет работать. Проводник только показывает упрощенное представление папки, которая содержит на самом деле много различных папок для различных видов блоков. Выполнение копии в нем из установщика не инициирует все операции, сделанные проводником на перетаскивании. (записанный здесь, потому что у меня нет достаточной репутации все же для комментария других сообщений).