Problem Overview
After migrating a Siemens WinCC project from V6.0 SPx (or V6.2 SPx) to WinCC V7.0, ANSI-C based C-Scripts that previously compiled and executed cleanly may suddenly fail to compile. The most common symptom is a duplicate-symbol or redefinition error that names the project's own C-function (for example SetAlarmFieldColor) and points at conflicting declarations inside the auto-generated WinCC header files. The error remains even after running Regenerate Headers and Compile All from the WinCC Script Editor toolbar.
Two related but distinct changes introduced in WinCC V7.0 drive this failure:
- The compiler-visible C-type
long intis no longer emitted in the regenerated header prototypes of internal WinCC API functions. Project functions and WinCC API prototypes that previously matched byte-for-byte (both written aslong int) now disagree at the parameter list, so the linker/compiler sees a signature mismatch. - Internal API prototypes were tightened. Parameters that used to be
long intin V6.2 are nowintorlongin V7.0. A project function whose parameter list was copied from the V6.2 header no longer matches the new V7.0 declaration.
The visible result on the Script Editor compilation output is an error such as:
error C2371: 'SetAlarmFieldColor' : redefinition; different basic types
AP_PBIB.h : see declaration of 'SetAlarmFieldColor'
AP_GLOB.h : see declaration of 'SetAlarmFieldColor'
Siemens technical support (in the case documented by the original poster, Siemens Belgium) has confirmed that the long int token is not emitted in the V7.0 regenerated WinCC headers. Scripts that depend on a literal long int signature must be rewritten.
long int change.
Affected Versions and Migration Path
The behavior change was introduced specifically in the V7.0 generation of WinCC. The migration paths that exhibit the problem in field deployments are:
| Source Version | Target Version | Symptoms | Reproducible |
|---|---|---|---|
| WinCC V6.0 (+SP1..SP4) | WinCC V7.0 | C-Scripts fail to compile; long int redefinition errors |
Yes |
| WinCC V6.2 (+SP1..SP3) | WinCC V7.0 | C-Scripts fail to compile; same root cause | Yes |
| WinCC V6.2 (+SP1..SP3) | WinCC V6.2 (re-migration) | No problem | No |
| WinCC V7.0 SP1 | WinCC V7.0 SP3 | Generally clean unless the project was originally written against V6.x | No (V7.0-internal projects OK) |
Verified across WinCC V7.0 base release and the V7.0 SP1/SP2/SP3 update releases. The function-prototype generator and the C-API header set were updated in V7.0 and have not been rolled back in subsequent SPs.
For the official Siemens documentation on supported upgrade paths, see the SIMATIC WinCC V7.0 Upgrade Installation Notes and the WinCC V7.0 Release Notes / Readme.
Root Cause Analysis
WinCC's C-Script engine emits two header files on demand (and on project open), and the C compiler uses those headers as the authoritative declarations for all WinCC-internal C functions (graphics API, alarm API, reporting API, etc.):
| Header | Location | Contents |
|---|---|---|
AP_PBIB.h |
[Project Directory]\Library\ |
Project-specific function declarations generated from .fct files inside the project (per picture and global). This is the file Regenerate Headers rebuilds. |
AP_GLOB.h |
[WinCC Installation Directory]\aplib\ |
Global declarations for the WinCC C-API (alarm, tag, picture, archive, report functions). Read-only at runtime; the file on disk is owned by the WinCC installation. |
When a project function is declared identically in both files (because the developer copied the prototype from AP_GLOB.h into the project's own .fct or into a hand-written C function in the project), the compiler emits a redefinition error.
Two independent reasons can introduce a mismatch in V7.0:
- Name collision on purpose. The project genuinely declares a function with the same name as a WinCC API function. In V6.2 the prototypes matched; in V7.0 the prototypes diverge (see the next section), so the compiler now classifies them as two different functions and rejects the project declaration as a conflicting redefinition.
-
Residual
long intkeyword. Even if the function names do not collide with the WinCC API, the project source still contains the literal textlong intin its own declarations. The Windows C compiler (MSVC) treatslongandlong intas identical for the parameter-passing ABI, but the WinCC header generator in V7.0 omitsint, so the function the project owns is binary-equal tolongwhile the WinCC API declaration islong. As long as both sides match, the script works; once either side changes (e.g.inton the project side,longon the WinCC side), the prototype diverges and any helper inline code, header cross-include, or C-runtime build step that compares signatures will fail.
Function Signature Changes Between V6.2 and V7.0
The original poster captured the exact delta. Below is the example reconstructed in tabular form so the pattern is reusable across all C-Scripts in the project.
| Position | WinCC V6.2 declaration | WinCC V7.0 declaration |
|---|---|---|
| Return type | long int |
long |
| Parameter 1: picture name | char* lpszPictureName |
char* lpszPictureName |
| Parameter 2: object name | char* lpszObjectName |
char* lpszObjectName |
| Parameter 3: alarm status | long int alarmstatus |
int alarmstatus |
| Parameter 4: default color | long int defaultcolor |
long defaultcolor |
| Parameter 5: background flash color | long int backgroundflashcolor |
long backgroundflashcolor |
The migration rule that the user distilled from the regenerated header is therefore:
- Every
long intin a project-side C-Script function must be re-spelled as eitherlong(32-bit on Win32/Win64 WinCC) orint, depending on which one the matching WinCC API uses inAP_GLOB.h. - Where the WinCC API has narrowed a parameter from
long inttoint(as withalarmstatusin the example), the project side must follow suit. If a 32-bit value must be passed, cast it explicitly with(int)at the call site to make the truncation visible and intentional.
Diagnostic Procedure: Locate the Conflicting Declaration
Before rewriting any code, confirm which of the two files owns each declaration. Regenerate Headers rewrites AP_PBIB.h; it does not touch AP_GLOB.h. If both files contain a declaration for the same function, the project has a name collision and must be renamed or the duplicate removed.
- Open the WinCC Explorer on the project (right-click Open in Explorer on the project name to get the path).
- Open the project library folder:
List every[Project Directory]\Library\.hfile (most importantlyAP_PBIB.h) and search for the failing function name (e.g.SetAlarmFieldColor). - Open the WinCC installation's API library folder:
The default installation path is[WinCC Installation Directory]\aplib\C:\Program Files\Siemens\Automation\WinCC\aplibon a 32-bit installation andC:\Program Files (x86)\Siemens\Automation\WinCC\aplibon a 64-bit Windows host. Search the same function name inAP_GLOB.h. - Compare the two declarations line-by-line. Record the differences in return type, parameter types, and qualifiers. A single missing
const, an extraunsigned, or alongvs.long intmismatch is enough to make the compiler treat them as two incompatible functions. - If the project file
AP_PBIB.hstill contains the legacylong intform after Regenerate Headers, the project source files (the.cor.cppedited in the Script Editor) still contain the old form. The header is regenerated from those sources, so the source must be edited first.
Step-by-Step Resolution
-
Take a backup. Copy the entire WinCC project directory and the WinCC installation folder (or at minimum
aplib) to a safe location. Migration rework should be reversible. - Open the project in WinCC Explorer. Do not start Graphics Designer yet. The error first needs to be analysed at the project level.
- Open the WinCC Script Editor (right-click Open on a picture that triggers the error, or use Global Script → C-Editor).
-
Run Regenerate Headers from the toolbar. Confirm in the output pane that
AP_PBIB.hwas rebuilt and re-open it. This is a no-op for the V7.0 problem, but it is the documented Siemens first step and it rules out cached-header issues. -
Search the project for the literal token
long int. Use the Script Editor's Find in Files across theLibrarydirectory and the global C-Editor project. Replace each occurrence withlongorintas appropriate, following the new V7.0 API declaration inAP_GLOB.h. -
For every project function whose name matches a WinCC API function (e.g.
SetAlarmFieldColor), rename the project function. The cleanest pattern is to prefix project helpers with the project or module name, such asProject_SetAlarmFieldColor. Update all call sites (C-Scripts, VBScript actions, dynamic dialogs) accordingly. - Recompile all C-Scripts with Compile All in the Script Editor. Check the Output pane for residual errors.
- Activate the project in WinCC Runtime and exercise the affected picture, alarm, or function in the runtime window. Confirm the alarm color logic in the example still changes correctly when the underlying tag transitions to the configured alarm state.
- Save a frozen copy of the corrected project for the next migration. Future WinCC V7.x service packs and any migration to V7.4 / V7.5 retain the V7.0 type rules for C-Script prototypes.
Code Migration Patterns
The following patterns cover the three common code shapes that need adjustment after migrating to V7.0.
Pattern A: Standalone helper that uses long int
Before (V6.2):
long int SetAlarmFieldColor(char* lpszPictureName,
char* lpszObjectName,
long int alarmstatus,
long int defaultcolor,
long int backgroundflashcolor)
{
/* ... */
return alarmstatus;
}
After (V7.0):
long SetAlarmFieldColor(char* lpszPictureName,
char* lpszObjectName,
int alarmstatus,
long defaultcolor,
long backgroundflashcolor)
{
/* ... */
return (long)alarmstatus;
}
Pattern B: Function with the same name as a WinCC API
If the project helper must coexist with the WinCC API, rename the project function and route through a wrapper.
/* Project wrapper, project side, kept in the C-Editor project */
long Project_SetAlarmFieldColor(char* lpszPictureName,
char* lpszObjectName,
int alarmstatus,
long defaultcolor,
long backgroundflashcolor)
{
/* Call the WinCC API or replace it with project logic */
return SetAlarmFieldColor(lpszPictureName,
lpszObjectName,
alarmstatus,
defaultcolor,
backgroundflashcolor);
}
Update every call site:
/* old */
SetAlarmFieldColor("Main.PDL", "AlarmField", st, 0, 0xFF0000);
/* new */
Project_SetAlarmFieldColor("Main.PDL", "AlarmField", st, 0, 0xFF0000);
Pattern C: Project struct with embedded long int fields
long int inside a typedef struct survives the type rules but should be modernised for consistency with the regenerated headers.
/* before */
typedef struct {
long int dwErrorCode;
long int dwTimestamp;
char szTagName[128];
} tag_alarm_record;
/* after */
typedef struct {
long dwErrorCode;
long dwTimestamp;
char szTagName[128];
} tag_alarm_record;
For binary compatibility on disk (e.g. when a structure is read from a binary tag or archive block), add a _Static_assert or a runtime sizeof() check so the size does not silently change after the rewrite.
Verification Procedure
After the migration patch, run the following checks before declaring the issue resolved.
-
Header reconciliation. For every function referenced in the project, open
AP_PBIB.hand the project source. There must be no entry inAP_PBIB.hwhose signature disagrees with the same name in the project source. There must be no name in the project that appears inAP_GLOB.hunless the signatures are byte-for-byte identical. -
Literal-token scan. Search the project for
long int,long int, andsigned long int. All occurrences should be zero in C-Script project files. (Comments and string literals may legitimately contain the text; restrict the search to code.) - Compiler output clean. Compile All in the Script Editor must finish with 0 errors and 0 warnings related to the migrated function set.
- Runtime smoke test. Activate the runtime. Trigger every alarm state that the project helper is supposed to handle. Verify the color change happens within one WinCC picture cycle (typically < 250 ms).
- Hot-restart regression. Save the runtime, stop WinCC, restart it, and confirm the project still loads and the C-Scripts still execute. This catches prototype mismatches that only surface during the second load (e.g. when the regenerated header is re-read).
-
Cross-tag test. If the project uses tags of type
32-bit signedor32-bit unsigned, bind them to a small C-Script that reads and writes the value. Confirm that values above 2,147,483,647 (or below -2,147,483,648 for signed) are handled according to the project's intent; if a parameter was narrowed fromlong inttoint, large values now truncate.
Related Compilation Errors and Edge Cases
| Symptom | Typical Cause | Resolution |
|---|---|---|
error C2371: redefinition; different basic types |
Project long int vs. WinCC long or int
|
Re-spell project type to match regenerated header |
error C2086: 'X' : redefinition |
Same function name in AP_PBIB.h and AP_GLOB.h
|
Rename project function |
error C2061: syntax error : identifier 'BOOL' |
Old project used Win16/Win32 BOOL macro from V6.0 days |
Replace with BOOL from apdefap.h or int
|
warning C4244: 'argument' : conversion from 'long' to 'int', possible loss of data |
Project passes a long where API now expects int
|
Add explicit cast at call site |
| Script compiles, runtime throws "Function not found" | Function renamed in code but call sites still point to old name | Re-search the project and update all SetAlarmFieldColor(...) calls |
| Script works in editor, fails when WinCC activates the project | Cached .cpy in [Project]\Library\ from a prior compile |
Delete *.cpy from Library\, then Regenerate Headers and Compile All
|
| Alarm color flashes once, then stops | Triggering tag transitions faster than the picture cycle after the parameter narrowing | Verify the alarm-status value fits in int; if not, store the high half in a project variable and merge on read |
When the Project Also Uses Win32 SDK Types
C-Scripts that include windows.h or pull in Win32 SDK headers (sometimes done for SYSTEMTIME, FILETIME, or CRITICAL_SECTION) are subject to an additional risk. The MSVC compiler that ships with WinCC V7.0 still defines long as 32 bits, but several SDK headers redefine long int through typedef on certain platforms. The project must avoid the literal combination long int WINAPI in any WINAPI callback; the WinCC runtime loader will treat the function symbol differently from the declaration the project compiled. The safe pattern is:
/* safe */
long WINAPI MyCallback(void);
/* unsafe - do not use */
long int WINAPI MyCallback(void);
Performance and Sizing Notes
The migration rewrite is structural, not runtime-impacting. C-Script functions execute inside the WinCC C-Script interpreter and the type narrowing from long int to int has no measurable effect on picture redraw time at typical alarm-event rates. For very high alarm churn (more than 1,000 alarm state changes per second per picture), consider:
- Moving the alarm color logic to an event-driven C-action attached to the alarm tag, so the function is only invoked on the transition rather than on every picture cycle.
- Using the WinCC alarm API in batch mode (
MSRTGetMsgState,MSRTGetMsgActual) rather than per-message polling. - Caching the last computed RGB color in a static variable inside the project helper so unchanged alarm states short-circuit the WinCC API call.
Prevention and Best Practices for Future Migrations
- Never copy a WinCC API prototype into a project function. Wrap the call site instead. This isolates the project from header-regeneration changes in future WinCC versions.
-
Avoid
long intin C-Scripts entirely. Uselongfor 32-bit signed andintfor the platform-default integer. Reservelong longfor 64-bit values, which are rare in WinCC tag traffic. - Add a regression test as a C-Script that, on project start, calls a small "header reconciliation" helper which iterates the project's known function names and confirms each one resolves to a single declaration. If the count goes above one, log an alarm or write to a diagnostic tag. This catches the issue at runtime long before the engineer notices it visually.
-
Track WinCC version in the project header. A single
#define WINCC_VERSION_AT_LEAST(x)macro at the top of the project C-Editor, evaluated against the WinCC installation'sSIMATIC WinCC\WinCC\bin\WinCC.exefile version, allows the project to compile differently for V6.2, V7.0, and V7.4 targets without manual rework. -
Keep a header-diff log. On every WinCC service pack, generate a fresh
AP_GLOB.h, diff it against the previous copy, and review the change set before updating the project. This makes the next V7.4 or V8.0 migration a controlled exercise rather than a firefight.
FAQ
Why did my C-Scripts work in WinCC V6.2 but fail in V7.0?
WinCC V7.0 regenerated its internal C-API headers with simplified integer types. The long int token was removed and some parameters were narrowed from long int to int. Project functions that still declared long int no longer match the V7.0 prototype, so the compiler reports a redefinition or signature-mismatch error. Replace long int with long or int to match the new V7.0 declarations in AP_GLOB.h.
Where are the WinCC C-API header files located?
Project-specific declarations are in [Project Directory]\Library\AP_PBIB.h, regenerated by the Script Editor's Regenerate Headers command. The global WinCC API declarations are in [WinCC Installation Directory]\aplib\AP_GLOB.h, typically C:\Program Files (x86)\Siemens\Automation\WinCC\aplib\AP_GLOB.h on a 64-bit Windows host. Compare the two files for any function name that appears in both.
Why does Regenerate Headers and Compile All not fix the error?
Because the regenerated AP_PBIB.h is rebuilt from the project's own C source files, and the project source files still contain the legacy long int token. The header generation is correct; the project source must be edited first. After editing, run Regenerate Headers and Compile All again.
Can I keep my project's function name identical to a WinCC API function?
You can if and only if the project signature is byte-for-byte identical to the V7.0 API signature, including the simplified types. In practice, renaming the project function (for example to Project_SetAlarmFieldColor) and routing through a wrapper is far more robust and survives future WinCC updates without further rework.
Does the same fix apply to WinCC V7.4, V7.5, or V8.0 migrations?
Yes. The rule "no long int in project C-Scripts, declare project wrappers with the simplified V7+ types" is valid through the current WinCC versions. The exact parameter list of any specific WinCC API function should always be confirmed against the target version's AP_GLOB.h before re-migration, because individual parameter types can change again between V7.0, V7.4, and V8.0.