Resolving WinCC V7.0 C-Script Long Int Migration Errors

David Krause14 min read
SiemensTroubleshootingWinCC
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

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:

  1. The compiler-visible C-type long int is 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 as long int) now disagree at the parameter list, so the linker/compiler sees a signature mismatch.
  2. Internal API prototypes were tightened. Parameters that used to be long int in V6.2 are now int or long in 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.

Scope of the issue: This affects projects that use C-Script (ANSI-C based WinCC scripting). VBScript actions, the global VBA environment, and the WinCC V7.0 "Industrial Graphics" (.NET) face different migration rules and are not affected by the 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:

  1. 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.
  2. Residual long int keyword. Even if the function names do not collide with the WinCC API, the project source still contains the literal text long int in its own declarations. The Windows C compiler (MSVC) treats long and long int as identical for the parameter-passing ABI, but the WinCC header generator in V7.0 omits int, so the function the project owns is binary-equal to long while the WinCC API declaration is long. As long as both sides match, the script works; once either side changes (e.g. int on the project side, long on 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 int in a project-side C-Script function must be re-spelled as either long (32-bit on Win32/Win64 WinCC) or int, depending on which one the matching WinCC API uses in AP_GLOB.h.
  • Where the WinCC API has narrowed a parameter from long int to int (as with alarmstatus in 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.

  1. Open the WinCC Explorer on the project (right-click Open in Explorer on the project name to get the path).
  2. Open the project library folder:
    [Project Directory]\Library\
    List every .h file (most importantly AP_PBIB.h) and search for the failing function name (e.g. SetAlarmFieldColor).
  3. Open the WinCC installation's API library folder:
    [WinCC Installation Directory]\aplib\
    The default installation path is C:\Program Files\Siemens\Automation\WinCC\aplib on a 32-bit installation and C:\Program Files (x86)\Siemens\Automation\WinCC\aplib on a 64-bit Windows host. Search the same function name in AP_GLOB.h.
  4. Compare the two declarations line-by-line. Record the differences in return type, parameter types, and qualifiers. A single missing const, an extra unsigned, or a long vs. long int mismatch is enough to make the compiler treat them as two incompatible functions.
  5. If the project file AP_PBIB.h still contains the legacy long int form after Regenerate Headers, the project source files (the .c or .cpp edited in the Script Editor) still contain the old form. The header is regenerated from those sources, so the source must be edited first.
Do not edit AP_GLOB.h. It is owned by the WinCC installation. Any manual change is overwritten on the next install, repair, or service-pack application. Fix the project side, never the API side.

Step-by-Step Resolution

  1. 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.
  2. Open the project in WinCC Explorer. Do not start Graphics Designer yet. The error first needs to be analysed at the project level.
  3. Open the WinCC Script Editor (right-click Open on a picture that triggers the error, or use Global ScriptC-Editor).
  4. Run Regenerate Headers from the toolbar. Confirm in the output pane that AP_PBIB.h was 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.
  5. Search the project for the literal token long int. Use the Script Editor's Find in Files across the Library directory and the global C-Editor project. Replace each occurrence with long or int as appropriate, following the new V7.0 API declaration in AP_GLOB.h.
  6. 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 as Project_SetAlarmFieldColor. Update all call sites (C-Scripts, VBScript actions, dynamic dialogs) accordingly.
  7. Recompile all C-Scripts with Compile All in the Script Editor. Check the Output pane for residual errors.
  8. 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.
  9. 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.

  1. Header reconciliation. For every function referenced in the project, open AP_PBIB.h and the project source. There must be no entry in AP_PBIB.h whose signature disagrees with the same name in the project source. There must be no name in the project that appears in AP_GLOB.h unless the signatures are byte-for-byte identical.
  2. Literal-token scan. Search the project for long int, long  int, and signed 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.)
  3. Compiler output clean. Compile All in the Script Editor must finish with 0 errors and 0 warnings related to the migrated function set.
  4. 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).
  5. 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).
  6. Cross-tag test. If the project uses tags of type 32-bit signed or 32-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 from long int to int, 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 int in C-Scripts entirely. Use long for 32-bit signed and int for the platform-default integer. Reserve long long for 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's SIMATIC WinCC\WinCC\bin\WinCC.exe file 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.

Back to blog