Migration from the Legacy TFMS_ API¶
If you have an existing DLL integration built against the old HydroSym TFMS_ function pointer API, this guide walks you through migrating to the new Plugin API.
Method mapping¶
| Old function | New method | Notes |
|---|---|---|
TFMS_MeridianGetPropertiesFunc |
GetProjectVariables |
Returns a map instead of writing to a PChar buffer |
TFMS_MeridianSetPropertiesFunc |
SetProjectVariables |
Receives a map instead of reading PChar pairs |
TFMS_MeridianUploadFileFunc |
UploadDrawing or SaveFile |
Use UploadDrawing for PDF/DXF uploads; SaveFile for vault copy |
TFMS_SQLGetDataFunc |
GetComponentParameters |
Returns structured JSON instead of writing to result buffers |
TFMS_TeamcenterGetSystemPartFunc |
GetComponentParameters |
Same — one method handles all ERP backends |
TFMS_TeamcenterBeginBomFunc + TFMS_NewBomItemFunc + TFMS_TeamcenterEndBomFunc |
UploadBom |
Single call with a complete list of BomItem objects |
TFMS_PDMSystemGetFileStatusFunc |
GetFileStatus |
Returns a structured status object |
TFMS_PDMSystemSaveFileFunc |
SaveFile |
Cleaner request/response; no buffer management |
TFMS_PDMSystemCheckOutFileFunc |
CheckOut |
|
TFMS_PDMSystemCheckInFileFunc |
CheckIn |
There is no direct equivalent of the old DLL initialization (DllMain / global setup). Use Initialize instead.
Key differences¶
1. JSON instead of PChar buffer management¶
Old API:
// Caller allocates a buffer, DLL writes to it
procedure TFMS_MeridianGetProperties(
AProjectPath: PChar;
ABuffer: PChar; ABufferSize: Integer);
New API — return a JSON object, no buffer management:
Your C# code simply returns a Dictionary<string, string>. The SDK handles serialization.
2. Single entry point¶
Old API: many exported functions, each registered as a function pointer.
New API: one exported function HydroSymPlugin_Invoke(method, requestJson, callback, ctx). The SDK handles dispatch to your overridden methods.
You do not need to manage DLL exports manually.
3. Structured error responses¶
Old API: boolean return value (true = OK, false = error), with error text in a shared buffer.
New API: PluginException with an error code and message:
4. Menu items declared in GetInfo¶
Old API: menu items were hardcoded in the DLL and registered via function pointers at startup.
New API: declare all menu items in GetInfo.menus. HydroSym reads them at load time.
Old code:
New code:
Step-by-step migration¶
Step 1: Create the new project¶
Step 2: Map your capabilities¶
Look at your old DLL and note which TFMS_ functions you implemented. Translate to capabilities:
Capabilities =
[
"getComponentParameters", // was: TFMS_SQLGetDataFunc
"getProjectVariables", // was: TFMS_MeridianGetPropertiesFunc
"setProjectVariables", // was: TFMS_MeridianSetPropertiesFunc
"uploadBom", // was: TFMS_Teamcenter*BomFunc
]
Step 3: Port Initialize¶
Your old DLL probably had global variables initialized in DllMain or a setup function. Move this to Initialize:
public override void Initialize(InitializeRequest request)
{
// was: global DllMain setup
_connectionString = ReadConfig(request.ConfigPath);
_db = new SqlConnection(_connectionString);
_db.Open();
}
Step 4: Port GetProjectVariables¶
// Old: TFMS_MeridianGetProperties(projectPath, buffer, bufferSize)
// New:
public override GetProjectVariablesResponse GetProjectVariables(
GetProjectVariablesRequest request)
{
var props = QueryErpProperties(request.ProjectPath);
return new GetProjectVariablesResponse { Variables = props };
}
Step 5: Port GetComponentParameters¶
// Old: TFMS_SQLGetData(articleCode, resultBuffer, bufferSize)
// New:
public override GetComponentParametersResponse GetComponentParameters(
GetComponentParametersRequest request)
{
var row = QueryErpArticle(request.ArticleCode);
return new GetComponentParametersResponse
{
ArticleCode = request.ArticleCode,
Status = row.Status,
Price = row.Price,
// ...
};
}
Step 6: Port UploadBom¶
The old API used three separate calls (BeginBom / NewBomItem × N / EndBom). The new API receives the complete list in one call:
// Old: three-phase call
// New:
public override UploadBomResponse UploadBom(UploadBomRequest request)
{
foreach (var item in request.Items ?? [])
{
InsertBomLine(item.ArticleCode, item.Quantity, item.Position);
}
return new UploadBomResponse { BomId = CommitBom() };
}
Step 7: Build and test¶
Step 8: Configure HydroSym¶
Replace the old [Plugin] INI settings with the new format:
; Old
PluginDLL=C:\...\OldPlugin.dll
PluginType=TFMS
; New
[Plugin]
Type=DLL
Path=C:\ProgramData\HydroSym\plugins\AcmeErpPlugin\AcmeErpPlugin.dll
Backward compatibility¶
HydroSym detects which API a DLL implements. If the DLL exports HydroSymPlugin_Invoke, it is treated as a new-style plugin. If it exports TFMS_RegisterPlugin, it is treated as a legacy plugin. Both can coexist within the same HydroSym installation for a transition period.
Once you have migrated and verified the new plugin, remove the old DLL from the INI.