This is an automated email from the ASF dual-hosted git repository.

martinzink pushed a commit to branch apache-rusty
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git

commit 5252c8acc4c7f2e8e2cfb07796713cb2ff503a4a
Author: Adam Debreceni <[email protected]>
AuthorDate: Mon Mar 2 14:03:04 2026 +0100

    MINIFICPP-2715 - Use a single integer as c api version
    MINIFICPP-2715 - Add extension loading tests for version verification
---
 Extensions.md                                      | 10 +--
 cmake/Extensions.cmake                             |  3 +-
 .../include/utils/ExtensionInitUtils.h             |  4 +-
 extensions/ExtensionInitializer.cpp                |  4 +-
 .../llamacpp/processors/ExtensionInitializer.cpp   |  8 +-
 extensions/opencv/OpenCVLoader.cpp                 |  6 +-
 .../python/pythonlibloader/PythonLibLoader.cpp     |  4 +-
 extensions/python/pythonloader/PyProcLoader.cpp    |  4 +-
 extensions/sftp/SFTPLoader.cpp                     |  8 +-
 .../include/core/extension/ApiVersion.h            | 27 +++----
 libminifi/include/core/extension/Extension.h       | 15 ++--
 .../src/core/extension/ApiVersion.cpp              | 31 ++++----
 libminifi/src/core/extension/Extension.cpp         | 74 +++++++++---------
 libminifi/src/minifi-c.cpp                         | 15 ++--
 libminifi/test/integration/CMakeLists.txt          |  2 +
 .../extension-verification-test/CApiExtension.cpp  | 26 ++++---
 .../extension-verification-test/CMakeLists.txt     | 81 +++++++++++++++++++
 .../CppApiExtension.cpp                            | 20 ++---
 .../CreateNotCalled.cpp                            | 24 ++----
 .../ExtensionVerificationTests.cpp                 | 91 ++++++++++++++++++++++
 .../InvalidMissingInitExtension.cpp                | 24 +-----
 .../extension-verification-test/dummy-cpp-api.def  |  3 +
 minifi-api/include/minifi-c/minifi-c.h             | 11 ++-
 23 files changed, 317 insertions(+), 178 deletions(-)

diff --git a/Extensions.md b/Extensions.md
index f71991824..376a29dbc 100644
--- a/Extensions.md
+++ b/Extensions.md
@@ -30,8 +30,7 @@ One possible example of this is:
 ```C++
 extern "C" const char* const MinifiApiVersion = MINIFI_API_VERSION;
 
-extern "C" MinifiExtension* MinifiInitExtension(MinifiConfig* /*config*/) {
-  MinifiExtension* extension = nullptr;
+extern "C" void MinifiInitExtension(MinifiExtension* extension, MinifiConfig* 
/*config*/) {
   
minifi::api::core::useProcessorClassDescription<minifi::extensions::llamacpp::processors::RunLlamaCppInference>([&]
 (const MinifiProcessorClassDefinition& description) {
     MinifiExtensionCreateInfo ext_create_info{
       .name = minifi::api::utils::toStringView(MAKESTRING(EXTENSION_NAME)),
@@ -41,9 +40,8 @@ extern "C" MinifiExtension* MinifiInitExtension(MinifiConfig* 
/*config*/) {
       .processors_count = 1,
       .processors_ptr = &description,
     };
-    extension = MinifiCreateExtension(&ext_create_info);
+    MinifiCreateExtension(extension, &ext_create_info);
   });
-  return extension;
 }
 ```
 
@@ -69,7 +67,7 @@ Some extensions (e.g. `OpenCVExtension`) require 
initialization before use.
 You need to define an `MinifiInitCppExtension` function of type 
`MinifiExtension*(MinifiConfig*)` to be called.
 
 ```C++
-extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) {
+extern "C" void MinifiInitCppExtension(MinifiExtension* extension, 
MinifiConfig* /*config*/) {
   const auto success = 
org::apache::nifi::minifi::utils::Environment::setEnvironmentVariable("OPENCV_FFMPEG_CAPTURE_OPTIONS",
 "rtsp_transport;udp", false /*overwrite*/);
   if (!success) {
     return nullptr;
@@ -84,7 +82,7 @@ extern "C" MinifiExtension* 
MinifiInitCppExtension(MinifiConfig* /*config*/) {
     .controller_services_count = 0,
     .controller_services_ptr = nullptr,
   };
-  return MinifiCreateCppExtension(&ext_create_info);
+  minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info);
 }
 ```
 
diff --git a/cmake/Extensions.cmake b/cmake/Extensions.cmake
index 6ea93f1cb..6e25d288b 100644
--- a/cmake/Extensions.cmake
+++ b/cmake/Extensions.cmake
@@ -31,8 +31,7 @@ macro(register_extension extension-name 
extension-display-name extension-guard d
         target_sources(${extension-name} PRIVATE 
${CMAKE_SOURCE_DIR}/extensions/ExtensionInitializer.cpp)
     endif()
     target_compile_definitions(${extension-name}
-        PRIVATE "MODULE_NAME=${extension-name}"
-        PRIVATE "BUILD_ID_VARIABLE_NAME=${build-id-variable-name}")
+        PRIVATE "MODULE_NAME=${extension-name}")
     set_target_properties(${extension-name} PROPERTIES
         ENABLE_EXPORTS True
         POSITION_INDEPENDENT_CODE ON)
diff --git a/extension-framework/include/utils/ExtensionInitUtils.h 
b/extension-framework/include/utils/ExtensionInitUtils.h
index 57f1d063f..75da5c1ae 100644
--- a/extension-framework/include/utils/ExtensionInitUtils.h
+++ b/extension-framework/include/utils/ExtensionInitUtils.h
@@ -30,8 +30,8 @@ inline MinifiStringView toStringView(std::string_view str) {
 
 using ConfigReader = std::function<std::optional<std::string>(std::string_view 
key)>;
 
-static inline MinifiExtension* MinifiCreateCppExtension(const 
MinifiExtensionCreateInfo* create_info) {
-  return MINIFI_CREATE_EXTENSION_FN(create_info);
+static inline void MinifiCreateCppExtension(MinifiExtension* extension, const 
MinifiExtensionCreateInfo* create_info) {
+  MINIFI_CREATE_EXTENSION_FN(extension, create_info);
 }
 
 }  // namespace org::apache::nifi::minifi::utils
diff --git a/extensions/ExtensionInitializer.cpp 
b/extensions/ExtensionInitializer.cpp
index 3f44395f9..45697af8b 100644
--- a/extensions/ExtensionInitializer.cpp
+++ b/extensions/ExtensionInitializer.cpp
@@ -22,7 +22,7 @@
 
 namespace minifi = org::apache::nifi::minifi;
 
-extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) {
+extern "C" void MinifiInitCppExtension(MinifiExtension* extension, 
MinifiConfig* /*config*/) {
   MinifiExtensionCreateInfo ext_create_info{
     .name = minifi::utils::toStringView(MAKESTRING(MODULE_NAME)),
     .version = minifi::utils::toStringView(minifi::AgentBuild::VERSION),
@@ -33,5 +33,5 @@ extern "C" MinifiExtension* 
MinifiInitCppExtension(MinifiConfig* /*config*/) {
     .controller_services_count = 0,
     .controller_services_ptr = nullptr,
   };
-  return minifi::utils::MinifiCreateCppExtension(&ext_create_info);
+  minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info);
 }
diff --git a/extensions/llamacpp/processors/ExtensionInitializer.cpp 
b/extensions/llamacpp/processors/ExtensionInitializer.cpp
index 4da94d071..54d893f23 100644
--- a/extensions/llamacpp/processors/ExtensionInitializer.cpp
+++ b/extensions/llamacpp/processors/ExtensionInitializer.cpp
@@ -24,10 +24,9 @@
 
 namespace minifi = org::apache::nifi::minifi;
 
-extern "C" const char* const MinifiApiVersion = MINIFI_API_VERSION;
+extern "C" const uint32_t MinifiApiVersion = MINIFI_API_VERSION;
 
-extern "C" MinifiExtension* MinifiInitExtension(MinifiConfig* /*config*/) {
-  MinifiExtension* extension = nullptr;
+extern "C" void MinifiInitExtension(MinifiExtension* extension, MinifiConfig* 
/*config*/) {
   
minifi::api::core::useProcessorClassDescription<minifi::extensions::llamacpp::processors::RunLlamaCppInference>([&]
 (const MinifiProcessorClassDefinition& description) {
     MinifiExtensionCreateInfo ext_create_info{
       .name = minifi::api::utils::toStringView(MAKESTRING(EXTENSION_NAME)),
@@ -39,7 +38,6 @@ extern "C" MinifiExtension* MinifiInitExtension(MinifiConfig* 
/*config*/) {
       .controller_services_count = 0,
       .controller_services_ptr = nullptr,
     };
-    extension = MinifiCreateExtension(&ext_create_info);
+    MinifiCreateExtension(extension, &ext_create_info);
   });
-  return extension;
 }
diff --git a/extensions/opencv/OpenCVLoader.cpp 
b/extensions/opencv/OpenCVLoader.cpp
index 1dc69c73e..6d506807d 100644
--- a/extensions/opencv/OpenCVLoader.cpp
+++ b/extensions/opencv/OpenCVLoader.cpp
@@ -24,7 +24,7 @@
 
 namespace minifi = org::apache::nifi::minifi;
 
-extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) {
+extern "C" void MinifiInitCppExtension(MinifiExtension* extension, 
MinifiConfig* /*config*/) {
   // By default in OpenCV, ffmpeg capture is hardcoded to use TCP and this is 
a workaround
   // also if UDP timeout, ffmpeg will retry with TCP
   // Note:
@@ -32,7 +32,7 @@ extern "C" MinifiExtension* 
MinifiInitCppExtension(MinifiConfig* /*config*/) {
   // 2. The command will not overwrite value if 
"OPENCV_FFMPEG_CAPTURE_OPTIONS" already exists.
   const auto success = 
org::apache::nifi::minifi::utils::Environment::setEnvironmentVariable("OPENCV_FFMPEG_CAPTURE_OPTIONS",
 "rtsp_transport;udp", false /*overwrite*/);
   if (!success) {
-    return nullptr;
+    return;
   }
   MinifiExtensionCreateInfo ext_create_info{
     .name = minifi::utils::toStringView(MAKESTRING(MODULE_NAME)),
@@ -44,5 +44,5 @@ extern "C" MinifiExtension* 
MinifiInitCppExtension(MinifiConfig* /*config*/) {
     .controller_services_count = 0,
     .controller_services_ptr = nullptr,
   };
-  return minifi::utils::MinifiCreateCppExtension(&ext_create_info);
+  minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info);
 }
diff --git a/extensions/python/pythonlibloader/PythonLibLoader.cpp 
b/extensions/python/pythonlibloader/PythonLibLoader.cpp
index 45aea023e..99ed9b612 100644
--- a/extensions/python/pythonlibloader/PythonLibLoader.cpp
+++ b/extensions/python/pythonlibloader/PythonLibLoader.cpp
@@ -98,7 +98,7 @@ class PythonLibLoader {
   std::shared_ptr<minifi::core::logging::Logger> logger_ = 
minifi::core::logging::LoggerFactory<PythonLibLoader>::getLogger();
 };
 
-extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* config) {
+extern "C" void MinifiInitCppExtension(MinifiExtension* extension, 
MinifiConfig* config) {
   static PythonLibLoader python_lib_loader([&] (std::string_view key) -> 
std::optional<std::string> {
     std::optional<std::string> result;
     MinifiConfigGet(config, minifi::utils::toStringView(key), [] (void* 
user_data, MinifiStringView value) {
@@ -116,5 +116,5 @@ extern "C" MinifiExtension* 
MinifiInitCppExtension(MinifiConfig* config) {
     .controller_services_count = 0,
     .controller_services_ptr = nullptr,
   };
-  return minifi::utils::MinifiCreateCppExtension(&ext_create_info);
+  minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info);
 }
diff --git a/extensions/python/pythonloader/PyProcLoader.cpp 
b/extensions/python/pythonloader/PyProcLoader.cpp
index 23f54eca7..6b2be2cf0 100644
--- a/extensions/python/pythonloader/PyProcLoader.cpp
+++ b/extensions/python/pythonloader/PyProcLoader.cpp
@@ -33,7 +33,7 @@ static minifi::extensions::python::PythonCreator& 
getPythonCreator() {
 // the symbols of the python library
 extern "C" const int LOAD_MODULE_AS_GLOBAL = 1;
 
-extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* config) {
+extern "C" void MinifiInitCppExtension(MinifiExtension* extension, 
MinifiConfig* config) {
   getPythonCreator().configure([&] (std::string_view key) -> 
std::optional<std::string> {
     std::optional<std::string> result;
     MinifiConfigGet(config, minifi::utils::toStringView(key), [] (void* 
user_data, MinifiStringView value) {
@@ -51,5 +51,5 @@ extern "C" MinifiExtension* 
MinifiInitCppExtension(MinifiConfig* config) {
     .controller_services_count = 0,
     .controller_services_ptr = nullptr,
   };
-  return minifi::utils::MinifiCreateCppExtension( &ext_create_info);
+  minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info);
 }
diff --git a/extensions/sftp/SFTPLoader.cpp b/extensions/sftp/SFTPLoader.cpp
index 4f3fe71b8..5f4a4be9e 100644
--- a/extensions/sftp/SFTPLoader.cpp
+++ b/extensions/sftp/SFTPLoader.cpp
@@ -25,13 +25,13 @@
 
 namespace minifi = org::apache::nifi::minifi;
 
-extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) {
+extern "C" void MinifiInitCppExtension(MinifiExtension* extension, 
MinifiConfig* /*config*/) {
   if (libssh2_init(0) != 0) {
-    return nullptr;
+    return;
   }
   if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {
     libssh2_exit();
-    return nullptr;
+    return;
   }
   MinifiExtensionCreateInfo ext_create_info{
     .name = minifi::utils::toStringView(MAKESTRING(MODULE_NAME)),
@@ -46,5 +46,5 @@ extern "C" MinifiExtension* 
MinifiInitCppExtension(MinifiConfig* /*config*/) {
     .controller_services_count = 0,
     .controller_services_ptr = nullptr,
   };
-  return minifi::utils::MinifiCreateCppExtension(&ext_create_info);
+  minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info);
 }
diff --git a/extension-framework/include/utils/ExtensionInitUtils.h 
b/libminifi/include/core/extension/ApiVersion.h
similarity index 53%
copy from extension-framework/include/utils/ExtensionInitUtils.h
copy to libminifi/include/core/extension/ApiVersion.h
index 57f1d063f..1cb1b9617 100644
--- a/extension-framework/include/utils/ExtensionInitUtils.h
+++ b/libminifi/include/core/extension/ApiVersion.h
@@ -1,5 +1,5 @@
 /**
- * Licensed to the Apache Software Foundation (ASF) under one or more
+* Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
@@ -14,24 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#pragma once
-
-#include <string>
-#include <string_view>
-#include <optional>
-#include <functional>
-#include "minifi-c/minifi-c.h"
 
-namespace org::apache::nifi::minifi::utils {
+#pragma once
 
-inline MinifiStringView toStringView(std::string_view str) {
-  return MinifiStringView{.data = str.data(), .length = str.length()};
-}
+#include <cstdint>
+#include  <string>
 
-using ConfigReader = std::function<std::optional<std::string>(std::string_view 
key)>;
+namespace org::apache::nifi::minifi::core::extension {
 
-static inline MinifiExtension* MinifiCreateCppExtension(const 
MinifiExtensionCreateInfo* create_info) {
-  return MINIFI_CREATE_EXTENSION_FN(create_info);
-}
+uint32_t getAgentApiVersion();
+uint32_t getMinSupportedApiVersion();
+void test_setAgentApiVersion(uint32_t api_version);
+void test_setMinSupportedApiVersion(uint32_t min_api_version);
 
-}  // namespace org::apache::nifi::minifi::utils
+}  // namespace org::apache::nifi::minifi::core::extension
diff --git a/libminifi/include/core/extension/Extension.h 
b/libminifi/include/core/extension/Extension.h
index 2a71a6fbc..85cf4fc60 100644
--- a/libminifi/include/core/extension/Extension.h
+++ b/libminifi/include/core/extension/Extension.h
@@ -25,6 +25,7 @@
 #include "minifi-c/minifi-c.h"
 #include "minifi-cpp/core/logging/Logger.h"
 #include "minifi-cpp/properties/Configure.h"
+#include "ApiVersion.h"
 
 namespace org::apache::nifi::minifi::core::extension {
 
@@ -39,12 +40,6 @@ class Extension {
     void* user_data;
   };
 
-  struct Version {
-    int major{MINIFI_API_MAJOR_VERSION};
-    int minor{MINIFI_API_MINOR_VERSION};
-    int patch{MINIFI_API_PATCH_VERSION};
-  };
-
   Extension(std::string name, std::filesystem::path library_path);
 
   Extension(const Extension&) = delete;
@@ -56,7 +51,7 @@ class Extension {
 
   bool initialize(const std::shared_ptr<minifi::Configure>& configure);
 
-  Version version() const {return version_;}
+  bool setInfo(Info info);
 
  private:
 #ifdef WIN32
@@ -76,12 +71,12 @@ class Extension {
   bool unload();
   void* findSymbol(const char* name);
 
-  std::string name_;
+  std::string library_name_;
   std::filesystem::path library_path_;
   gsl::owner<void*> handle_ = nullptr;
 
-  Version version_{};
-  std::unique_ptr<Info> info_;
+  std::optional<Info> info_;
+  uint32_t api_version_{0};
 
   const std::shared_ptr<logging::Logger> logger_;
 };
diff --git a/extension-framework/include/utils/ExtensionInitUtils.h 
b/libminifi/src/core/extension/ApiVersion.cpp
similarity index 53%
copy from extension-framework/include/utils/ExtensionInitUtils.h
copy to libminifi/src/core/extension/ApiVersion.cpp
index 57f1d063f..15f59d18b 100644
--- a/extension-framework/include/utils/ExtensionInitUtils.h
+++ b/libminifi/src/core/extension/ApiVersion.cpp
@@ -1,5 +1,5 @@
 /**
- * Licensed to the Apache Software Foundation (ASF) under one or more
+* Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
@@ -14,24 +14,29 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#pragma once
 
-#include <string>
-#include <string_view>
-#include <optional>
-#include <functional>
+#include "core/extension/ApiVersion.h"
 #include "minifi-c/minifi-c.h"
 
-namespace org::apache::nifi::minifi::utils {
+namespace org::apache::nifi::minifi::core::extension {
 
-inline MinifiStringView toStringView(std::string_view str) {
-  return MinifiStringView{.data = str.data(), .length = str.length()};
+static uint32_t agent_api_version{MINIFI_API_VERSION};
+static uint32_t min_supported_api_version{MINIFI_API_VERSION};
+
+uint32_t getAgentApiVersion() {
+  return agent_api_version;
+}
+
+void test_setAgentApiVersion(uint32_t api_version) {
+  agent_api_version = api_version;
 }
 
-using ConfigReader = std::function<std::optional<std::string>(std::string_view 
key)>;
+uint32_t getMinSupportedApiVersion() {
+  return min_supported_api_version;
+}
 
-static inline MinifiExtension* MinifiCreateCppExtension(const 
MinifiExtensionCreateInfo* create_info) {
-  return MINIFI_CREATE_EXTENSION_FN(create_info);
+void test_setMinSupportedApiVersion(uint32_t min_api_version) {
+  min_supported_api_version = min_api_version;
 }
 
-}  // namespace org::apache::nifi::minifi::utils
+}  // namespace org::apache::nifi::minifi::core::extension
\ No newline at end of file
diff --git a/libminifi/src/core/extension/Extension.cpp 
b/libminifi/src/core/extension/Extension.cpp
index 62ded29c4..f0a935c73 100644
--- a/libminifi/src/core/extension/Extension.cpp
+++ b/libminifi/src/core/extension/Extension.cpp
@@ -41,8 +41,8 @@
 
 namespace org::apache::nifi::minifi::core::extension {
 
-Extension::Extension(std::string name, std::filesystem::path library_path)
-  : name_(std::move(name)),
+Extension::Extension(std::string library_name, std::filesystem::path 
library_path)
+  : library_name_(std::move(library_name)),
     library_path_(std::move(library_path)),
     logger_(logging::LoggerFactory<Extension>::getLogger()) {
 }
@@ -55,59 +55,51 @@ bool Extension::load(bool global) {
     handle_ = dlopen(library_path_.string().c_str(), RTLD_NOW | RTLD_LOCAL);  
// NOLINT(cppcoreguidelines-owning-memory)
   }
   if (!handle_) {
-    logger_->log_error("Failed to load extension '{}' at '{}': {}", name_, 
library_path_, dlerror());
+    logger_->log_error("Failed to load extension '{}' at '{}': {}", 
library_name_, library_path_, dlerror());
     return false;
   }
-  logger_->log_trace("Dlopen succeeded for extension '{}' at '{}'", name_, 
library_path_);
+  logger_->log_trace("Dlopen succeeded for extension '{}' at '{}'", 
library_name_, library_path_);
   if (findSymbol("MinifiInitCppExtension")) {
-    logger_->log_trace("Loaded cpp extension '{}' at '{}'", name_, 
library_path_);
+    logger_->log_trace("Loaded cpp extension '{}' at '{}'", library_name_, 
library_path_);
     return true;
   }
   if (!findSymbol("MinifiInitExtension")) {
-    logger_->log_error("Failed to load c extension '{}' at '{}': No 
initializer found", name_, library_path_);
+    logger_->log_error("Failed to load as c extension '{}' at '{}': No 
initializer found", library_name_, library_path_);
     return false;
   }
-  auto api_version = reinterpret_cast<const char* 
const*>(findSymbol("MinifiApiVersion"));
-  if (!api_version) {
-    logger_->log_error("Failed to load c extension '{}' at '{}': No 
MinifiApiVersion symbol found", name_, library_path_);
+  auto api_version_ptr = reinterpret_cast<const 
uint32_t*>(findSymbol("MinifiApiVersion"));
+  if (!api_version_ptr) {
+    logger_->log_error("Failed to load c extension '{}' at '{}': No 
MinifiApiVersion symbol found", library_name_, library_path_);
     return false;
   }
-  utils::SVMatch match;
-  if (!utils::regexSearch(*api_version, match, 
utils::Regex{R"(^([0-9]+)\.([0-9]+)\.([0-9]+)$)"})) {
-    logger_->log_error("Failed to load c extension '{}' at '{}': Api version 
is in invalid format: '{}'", name_, library_path_, *api_version);
+  api_version_ = *api_version_ptr;
+  if (api_version_ < getMinSupportedApiVersion()) {
+    logger_->log_error("Failed to load c extension '{}' at '{}': Api version 
is no longer supported, application supports {}-{} while extension is {}",
+        library_name_, library_path_, getMinSupportedApiVersion(), 
getAgentApiVersion(), api_version_);
     return false;
   }
-  gsl_Assert(match.size() == 4);
-  version_.major = std::stoi(match[1]);
-  version_.minor = std::stoi(match[2]);
-  version_.patch = std::stoi(match[3]);
-  if (version_.major != MINIFI_API_MAJOR_VERSION) {
-    logger_->log_error("Failed to load c extension '{}' at '{}': Api major 
version mismatch, application is '{}' while extension is '{}'",
-        name_, library_path_, MINIFI_API_VERSION, *api_version);
+  if (api_version_ > getAgentApiVersion()) {
+    logger_->log_error("Failed to load c extension '{}' at '{}': Extension is 
built for a newer version, application supports {}-{} while extension is {}",
+        library_name_, library_path_, getMinSupportedApiVersion(), 
getAgentApiVersion(), api_version_);
     return false;
   }
-  if (version_.minor > MINIFI_API_MINOR_VERSION) {
-    logger_->log_error("Failed to load c extension '{}' at '{}': Extension is 
built for a newer version, application is '{}' while extension is '{}'",
-        name_, library_path_, MINIFI_API_VERSION, *api_version);
-    return false;
-  }
-  logger_->log_debug("Loaded c extension '{}' at '{}': Application version is 
'{}', extension version is '{}'",
-        name_, library_path_, MINIFI_API_VERSION, *api_version);
+  logger_->log_debug("Loaded c extension '{}' at '{}': Application version is 
{}, extension version is {}",
+        library_name_, library_path_, getAgentApiVersion(), api_version_);
   return true;
 }
 
 bool Extension::unload() {
-  logger_->log_trace("Unloading library '{}' at '{}'", name_, library_path_);
+  logger_->log_trace("Unloading library '{}' at '{}'", library_name_, 
library_path_);
   if (!handle_) {
-    logger_->log_error("Extension does not have a handle_ '{}' at '{}'", 
name_, library_path_);
+    logger_->log_error("Extension does not have a handle_ '{}' at '{}'", 
library_name_, library_path_);
     return true;
   }
   dlerror();
   if (dlclose(handle_)) {
-    logger_->log_error("Failed to unload extension '{}' at '{}': {}", name_, 
library_path_, dlerror());
+    logger_->log_error("Failed to unload extension '{}' at '{}': {}", 
library_name_, library_path_, dlerror());
     return false;
   }
-  logger_->log_trace("Unloaded extension '{}' at '{}'", name_, library_path_);
+  logger_->log_trace("Unloaded extension '{}' at '{}'", library_name_, 
library_path_);
   handle_ = nullptr;
   return true;
 }
@@ -126,24 +118,34 @@ Extension::~Extension() {
   unload();
 }
 
+bool Extension::setInfo(Info info) {
+  if (info_) {
+    return false;
+  }
+  info_ = std::move(info);
+  return true;
+}
+
 bool Extension::initialize(const std::shared_ptr<minifi::Configure>& 
configure) {
-  logger_->log_trace("Initializing extension '{}'", name_);
+  logger_->log_trace("Initializing extension '{}'", library_name_);
   void* init_symbol_ptr = findSymbol("MinifiInitCppExtension");
   if (!init_symbol_ptr) {
     init_symbol_ptr = findSymbol("MinifiInitExtension");
   }
   if (!init_symbol_ptr) {
-    logger_->log_error("No initializer for '{}'", name_);
+    logger_->log_error("No initializer for '{}'", library_name_);
     return false;
   }
-  logger_->log_debug("Found initializer for '{}'", name_);
-  auto init_fn = 
reinterpret_cast<MinifiExtension*(*)(MinifiConfig*)>(init_symbol_ptr);
+  logger_->log_debug("Found initializer for '{}'", library_name_);
+  auto init_fn = reinterpret_cast<void(*)(MinifiExtension*, 
MinifiConfig*)>(init_symbol_ptr);
   auto config_handle = reinterpret_cast<MinifiConfig*>(configure.get());
-  info_.reset(reinterpret_cast<Info*>(init_fn(config_handle)));
+  auto extension_handle = reinterpret_cast<MinifiExtension*>(this);
+  init_fn(extension_handle, config_handle);
   if (!info_) {
-    logger_->log_error("Failed to initialize extension '{}'", name_);
+    logger_->log_error("Failed to initialize extension '{}'", library_name_);
     return false;
   }
+  logger_->log_debug("Initialized extension '{}', name = '{}', version = 
'{}'", library_name_, info_->name, info_->version);
   return true;
 }
 
diff --git a/libminifi/src/minifi-c.cpp b/libminifi/src/minifi-c.cpp
index b085dbf66..34ed49e57 100644
--- a/libminifi/src/minifi-c.cpp
+++ b/libminifi/src/minifi-c.cpp
@@ -290,10 +290,9 @@ void useCControllerServiceClassDescription(const 
MinifiControllerServiceClassDef
 
 extern "C" {
 
-MinifiExtension* MinifiCreateExtension(const MinifiExtensionCreateInfo* 
extension_create_info) {
+MinifiStatus MinifiCreateExtension(MinifiExtension* extension, const 
MinifiExtensionCreateInfo* extension_create_info) {
+  gsl_Assert(extension);
   gsl_Assert(extension_create_info);
-  auto current_extension = 
minifi::core::extension::ExtensionManager::getExtensionBeingInitialized();
-  gsl_Assert(current_extension);
   auto extension_name = toString(extension_create_info->name);
   minifi::BundleIdentifier bundle{
     .name = extension_name,
@@ -316,16 +315,20 @@ MinifiExtension* MinifiCreateExtension(const 
MinifiExtensionCreateInfo* extensio
       bundle_components.controller_services.emplace_back(description);
     });
   }
-  return reinterpret_cast<MinifiExtension*>(new 
org::apache::nifi::minifi::core::extension::Extension::Info{
+  bool success = 
reinterpret_cast<org::apache::nifi::minifi::core::extension::Extension*>(extension)->setInfo(org::apache::nifi::minifi::core::extension::Extension::Info{
     .name = toString(extension_create_info->name),
     .version = toString(extension_create_info->version),
     .deinit = extension_create_info->deinit,
     .user_data = extension_create_info->user_data
   });
+  if (success) {
+    return MINIFI_STATUS_SUCCESS;
+  }
+  return MINIFI_STATUS_UNKNOWN_ERROR;
 }
 
-MinifiExtension* MINIFI_CREATE_EXTENSION_FN(const MinifiExtensionCreateInfo* 
extension_create_info) {
-  return MinifiCreateExtension(extension_create_info);
+MinifiStatus MINIFI_CREATE_EXTENSION_FN(MinifiExtension* extension, const 
MinifiExtensionCreateInfo* extension_create_info) {
+  return MinifiCreateExtension(extension, extension_create_info);
 }
 
 MinifiStatus MinifiProcessContextGetProperty(MinifiProcessContext* context, 
MinifiStringView property_name, MinifiFlowFile* flowfile,
diff --git a/libminifi/test/integration/CMakeLists.txt 
b/libminifi/test/integration/CMakeLists.txt
index 3fb3fd88a..44e98f76a 100644
--- a/libminifi/test/integration/CMakeLists.txt
+++ b/libminifi/test/integration/CMakeLists.txt
@@ -45,3 +45,5 @@ ENDFOREACH()
 target_link_libraries(OnScheduleErrorHandlingTests minifi-test-processors)
 
 message("-- Finished building ${INT_TEST_COUNT} integration test file(s)...")
+
+add_subdirectory(extension-verification-test)
diff --git a/extensions/ExtensionInitializer.cpp 
b/libminifi/test/integration/extension-verification-test/CApiExtension.cpp
similarity index 65%
copy from extensions/ExtensionInitializer.cpp
copy to libminifi/test/integration/extension-verification-test/CApiExtension.cpp
index 3f44395f9..bbd51809a 100644
--- a/extensions/ExtensionInitializer.cpp
+++ b/libminifi/test/integration/extension-verification-test/CApiExtension.cpp
@@ -1,5 +1,5 @@
 /**
- *
+*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
@@ -15,23 +15,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "minifi-c/minifi-c.h"
-#include "utils/ExtensionInitUtils.h"
-#include "minifi-cpp/agent/agent_version.h"
-#include "core/Resource.h"
+
+#include "api/core/Resource.h"
+#include "api/utils/minifi-c-utils.h"
+
+#define MKSOC(x) #x
+#define MAKESTRING(x) MKSOC(x)  // NOLINT(cppcoreguidelines-macro-usage)
 
 namespace minifi = org::apache::nifi::minifi;
 
-extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) {
+extern "C" const uint32_t MinifiApiVersion = MINIFI_TEST_API_VERSION;
+
+extern "C" void MinifiInitExtension(MinifiExtension* extension, MinifiConfig* 
/*config*/) {
   MinifiExtensionCreateInfo ext_create_info{
-    .name = minifi::utils::toStringView(MAKESTRING(MODULE_NAME)),
-    .version = minifi::utils::toStringView(minifi::AgentBuild::VERSION),
+    .name = minifi::api::utils::toStringView(MAKESTRING(EXTENSION_NAME)),
+    .version = minifi::api::utils::toStringView(MAKESTRING(EXTENSION_VERSION)),
     .deinit = nullptr,
     .user_data = nullptr,
     .processors_count = 0,
     .processors_ptr = nullptr,
-    .controller_services_count = 0,
-    .controller_services_ptr = nullptr,
   };
-  return minifi::utils::MinifiCreateCppExtension(&ext_create_info);
-}
+  MinifiCreateExtension(extension, &ext_create_info);
+}
\ No newline at end of file
diff --git 
a/libminifi/test/integration/extension-verification-test/CMakeLists.txt 
b/libminifi/test/integration/extension-verification-test/CMakeLists.txt
new file mode 100644
index 000000000..fa428b044
--- /dev/null
+++ b/libminifi/test/integration/extension-verification-test/CMakeLists.txt
@@ -0,0 +1,81 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+#
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+add_minifi_executable(ExtensionVerificationTests 
ExtensionVerificationTests.cpp)
+createIntegrationTests(ExtensionVerificationTests)
+target_link_libraries(${testfilename} core-minifi Catch2WithMain 
Threads::Threads)
+add_test(NAME ExtensionVerificationTests COMMAND ExtensionVerificationTests)
+
+function(create_loading_test_extension extension-name extension-main)
+    add_library(${extension-name} SHARED ${extension-main})
+    add_dependencies(ExtensionVerificationTests ${extension-name})
+    target_compile_definitions(${extension-name} PRIVATE 
MODULE_NAME=${extension-name})
+    set_target_properties(${extension-name} PROPERTIES ENABLE_EXPORTS True 
POSITION_INDEPENDENT_CODE ON)
+    if(WIN32)
+        set_target_properties(${extension-name} PROPERTIES
+            RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
+            ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
+            WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
+    else()
+        set_target_properties(${extension-name} PROPERTIES 
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
+    endif()
+endfunction()
+
+function(create_c_test_extension extension-name custom_api_version)
+    set(extension-name "test-extension-loading-${extension-name}")
+    create_loading_test_extension(${extension-name} CApiExtension.cpp)
+    target_link_libraries(${extension-name} minifi-cpp-extension-lib)
+    target_compile_definitions(${extension-name} PRIVATE 
MINIFI_TEST_API_VERSION=${custom_api_version})
+    target_compile_definitions(${extension-name}
+            PRIVATE "EXTENSION_NAME=${extension-name}" 
"EXTENSION_VERSION=${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
+endfunction()
+
+add_library(dummy-core-minifi INTERFACE)
+target_include_directories(dummy-core-minifi INTERFACE 
$<TARGET_PROPERTY:minifi-extension-framework,INTERFACE_INCLUDE_DIRECTORIES>)
+if (WIN32)
+    set(DUMMY_IMPORT_LIB_FILE ${CMAKE_CURRENT_BINARY_DIR}/dummy-cpp-api.lib)
+    add_custom_target(dummy_cpp_api_import_lib
+            COMMAND lib.exe /def:${CMAKE_CURRENT_SOURCE_DIR}/dummy-cpp-api.def 
/out:${IMPORT_LIB_FILE} /machine:x64
+            BYPRODUCTS ${IMPORT_LIB_FILE}
+    )
+
+    add_dependencies(dummy-core-minifi dummy_cpp_api_import_lib)
+    target_link_libraries(dummy-core-minifi INTERFACE ${IMPORT_LIB_FILE})
+elseif (APPLE)
+    target_link_options(dummy-core-minifi INTERFACE -undefined dynamic_lookup)
+endif()
+
+create_loading_test_extension(test-extension-loading-invalid-build-id-cpp 
CppApiExtension.cpp)
+target_link_libraries(test-extension-loading-invalid-build-id-cpp 
dummy-core-minifi)
+target_compile_definitions(test-extension-loading-invalid-build-id-cpp PRIVATE 
MINIFI_CREATE_EXTENSION_FN=MinifiCreateCppExtension_NonMatchingBuildId)
+
+create_loading_test_extension(test-extension-loading-valid-build-id-cpp 
CppApiExtension.cpp)
+target_link_libraries(test-extension-loading-valid-build-id-cpp 
dummy-core-minifi)
+target_compile_definitions(test-extension-loading-valid-build-id-cpp PRIVATE 
MINIFI_CREATE_EXTENSION_FN=MinifiCreateCppExtension_${BUILD_IDENTIFIER})
+
+create_c_test_extension(max-version 10)
+create_c_test_extension(valid-version 7)
+create_c_test_extension(min-version 5)
+create_c_test_extension(greater-version 11)
+create_c_test_extension(smaller-version 4)
+create_loading_test_extension(test-extension-loading-missing-init 
InvalidMissingInitExtension.cpp)
+
+create_loading_test_extension(test-extension-loading-create-not-called 
CreateNotCalled.cpp)
+target_link_libraries(test-extension-loading-create-not-called minifi-c-api)
+target_compile_definitions(test-extension-loading-create-not-called PRIVATE 
MINIFI_TEST_API_VERSION=10)
diff --git a/extensions/ExtensionInitializer.cpp 
b/libminifi/test/integration/extension-verification-test/CppApiExtension.cpp
similarity index 71%
copy from extensions/ExtensionInitializer.cpp
copy to 
libminifi/test/integration/extension-verification-test/CppApiExtension.cpp
index 3f44395f9..59daee45d 100644
--- a/extensions/ExtensionInitializer.cpp
+++ b/libminifi/test/integration/extension-verification-test/CppApiExtension.cpp
@@ -1,5 +1,5 @@
 /**
- *
+*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
@@ -15,23 +15,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "minifi-c/minifi-c.h"
+
+#include <string_view>
 #include "utils/ExtensionInitUtils.h"
-#include "minifi-cpp/agent/agent_version.h"
-#include "core/Resource.h"
+
+#define MKSOC(x) #x
+#define MAKESTRING(x) MKSOC(x)  // NOLINT(cppcoreguidelines-macro-usage)
 
 namespace minifi = org::apache::nifi::minifi;
 
-extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) {
+extern "C" void MinifiInitCppExtension(MinifiExtension* extension, 
MinifiConfig* /*config*/) {
   MinifiExtensionCreateInfo ext_create_info{
     .name = minifi::utils::toStringView(MAKESTRING(MODULE_NAME)),
-    .version = minifi::utils::toStringView(minifi::AgentBuild::VERSION),
+    .version = minifi::utils::toStringView("1.0.0"),
     .deinit = nullptr,
     .user_data = nullptr,
     .processors_count = 0,
-    .processors_ptr = nullptr,
-    .controller_services_count = 0,
-    .controller_services_ptr = nullptr,
+    .processors_ptr = nullptr
   };
-  return minifi::utils::MinifiCreateCppExtension(&ext_create_info);
+  minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info);
 }
diff --git a/extension-framework/include/utils/ExtensionInitUtils.h 
b/libminifi/test/integration/extension-verification-test/CreateNotCalled.cpp
similarity index 57%
copy from extension-framework/include/utils/ExtensionInitUtils.h
copy to 
libminifi/test/integration/extension-verification-test/CreateNotCalled.cpp
index 57f1d063f..ec6e5394d 100644
--- a/extension-framework/include/utils/ExtensionInitUtils.h
+++ b/libminifi/test/integration/extension-verification-test/CreateNotCalled.cpp
@@ -1,4 +1,5 @@
 /**
+*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
@@ -14,24 +15,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#pragma once
 
-#include <string>
-#include <string_view>
-#include <optional>
-#include <functional>
-#include "minifi-c/minifi-c.h"
+#include "minifi-c.h"
 
-namespace org::apache::nifi::minifi::utils {
+extern "C" const uint32_t MinifiApiVersion = MINIFI_TEST_API_VERSION;
 
-inline MinifiStringView toStringView(std::string_view str) {
-  return MinifiStringView{.data = str.data(), .length = str.length()};
-}
-
-using ConfigReader = std::function<std::optional<std::string>(std::string_view 
key)>;
-
-static inline MinifiExtension* MinifiCreateCppExtension(const 
MinifiExtensionCreateInfo* create_info) {
-  return MINIFI_CREATE_EXTENSION_FN(create_info);
-}
-
-}  // namespace org::apache::nifi::minifi::utils
+extern "C" void MinifiInitExtension(MinifiExtension* extension, MinifiConfig* 
/*config*/) {
+  // NOT CALLING CREATE
+}
\ No newline at end of file
diff --git 
a/libminifi/test/integration/extension-verification-test/ExtensionVerificationTests.cpp
 
b/libminifi/test/integration/extension-verification-test/ExtensionVerificationTests.cpp
new file mode 100644
index 000000000..a31700bf7
--- /dev/null
+++ 
b/libminifi/test/integration/extension-verification-test/ExtensionVerificationTests.cpp
@@ -0,0 +1,91 @@
+/**
+*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CUSTOM_EXTENSION_INIT
+
+#include "unit/TestBase.h"
+#include "unit/Catch.h"
+#include "unit/TestUtils.h"
+#include "core/extension/ExtensionManager.h"
+#include "core/extension/ApiVersion.h"
+
+namespace minifi = org::apache::nifi::minifi;
+
+class ExtensionLoadingTestController {
+ public:
+  ExtensionLoadingTestController(std::string pattern): extension_manager_{[&] 
() {
+    LogTestController::getInstance().clear();
+    
LogTestController::getInstance().setTrace<core::extension::ExtensionManager>();
+    LogTestController::getInstance().setTrace<core::extension::Extension>();
+    minifi::core::extension::test_setAgentApiVersion(10);
+    minifi::core::extension::test_setMinSupportedApiVersion(5);
+    auto config = minifi::Configure::create();
+    config->set(minifi::Configuration::nifi_extension_path, pattern);
+    return config;
+  }()} {}
+
+ core::extension::ExtensionManager extension_manager_;
+};
+
+TEST_CASE("Can load cpp-api extensions with same build id") {
+  ExtensionLoadingTestController 
controller{"*test-extension-loading-valid-build-id-cpp*"};
+  REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded cpp 
extension 'test-extension-loading-valid-build-id-cpp'"));
+}
+
+TEST_CASE("Can load c-api extensions with max version") {
+  ExtensionLoadingTestController 
controller{"*test-extension-loading-max-version*"};
+  REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded c 
extension 'test-extension-loading-max-version'"));
+}
+
+TEST_CASE("Can't load cpp-api extensions with different build id") {
+  ExtensionLoadingTestController 
controller{"*test-extension-loading-invalid-build-id-cpp*"};
+  REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to 
load extension 'test-extension-loading-invalid-build-id-cpp'"));
+}
+
+TEST_CASE("Can load c-api extensions with min version") {
+  ExtensionLoadingTestController 
controller{"*test-extension-loading-min-version*"};
+  REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded c 
extension 'test-extension-loading-min-version'"));
+}
+
+TEST_CASE("Can load c-api extensions with valid version") {
+  ExtensionLoadingTestController 
controller{"*test-extension-loading-valid-version*"};
+  REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded c 
extension 'test-extension-loading-valid-version'"));
+}
+
+TEST_CASE("Can't load c-api extensions with greater version") {
+  ExtensionLoadingTestController 
controller{"*test-extension-loading-greater-version*"};
+  REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to 
load c extension 'test-extension-loading-greater-version'"));
+  REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Extension 
is built for a newer version"));
+}
+
+TEST_CASE("Can't load c-api extensions with smaller version") {
+  ExtensionLoadingTestController 
controller{"*test-extension-loading-smaller-version*"};
+  REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to 
load c extension 'test-extension-loading-smaller-version'"));
+  REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Api 
version is no longer supported, application supports 5-10 while extension is 
4"));
+}
+
+TEST_CASE("Can't load c-api extensions with no MinifiInitExtension function") {
+  ExtensionLoadingTestController 
controller{"*test-extension-loading-missing-init*"};
+  REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to 
load as c extension 'test-extension-loading-missing-init'"));
+}
+
+TEST_CASE("Can't load c-api extensions with no MinifiCreateExtension call") {
+  ExtensionLoadingTestController 
controller{"*test-extension-loading-create-not-called*"};
+  REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to 
initialize extension 'test-extension-loading-create-not-called'"));
+}
+
diff --git a/extension-framework/include/utils/ExtensionInitUtils.h 
b/libminifi/test/integration/extension-verification-test/InvalidMissingInitExtension.cpp
similarity index 56%
copy from extension-framework/include/utils/ExtensionInitUtils.h
copy to 
libminifi/test/integration/extension-verification-test/InvalidMissingInitExtension.cpp
index 57f1d063f..3fbb5023e 100644
--- a/extension-framework/include/utils/ExtensionInitUtils.h
+++ 
b/libminifi/test/integration/extension-verification-test/InvalidMissingInitExtension.cpp
@@ -1,4 +1,5 @@
 /**
+*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
@@ -13,25 +14,4 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- */
-#pragma once
-
-#include <string>
-#include <string_view>
-#include <optional>
-#include <functional>
-#include "minifi-c/minifi-c.h"
-
-namespace org::apache::nifi::minifi::utils {
-
-inline MinifiStringView toStringView(std::string_view str) {
-  return MinifiStringView{.data = str.data(), .length = str.length()};
-}
-
-using ConfigReader = std::function<std::optional<std::string>(std::string_view 
key)>;
-
-static inline MinifiExtension* MinifiCreateCppExtension(const 
MinifiExtensionCreateInfo* create_info) {
-  return MINIFI_CREATE_EXTENSION_FN(create_info);
-}
-
-}  // namespace org::apache::nifi::minifi::utils
+ */
\ No newline at end of file
diff --git 
a/libminifi/test/integration/extension-verification-test/dummy-cpp-api.def 
b/libminifi/test/integration/extension-verification-test/dummy-cpp-api.def
new file mode 100644
index 000000000..8da19c75e
--- /dev/null
+++ b/libminifi/test/integration/extension-verification-test/dummy-cpp-api.def
@@ -0,0 +1,3 @@
+LIBRARY core-minifi.dll
+EXPORTS
+  MinifiCreateCppExtension_NonMatchingBuildId
diff --git a/minifi-api/include/minifi-c/minifi-c.h 
b/minifi-api/include/minifi-c/minifi-c.h
index fe27ca565..e6a96755b 100644
--- a/minifi-api/include/minifi-c/minifi-c.h
+++ b/minifi-api/include/minifi-c/minifi-c.h
@@ -34,11 +34,6 @@ extern "C" {
 #define MINIFI_PRIVATE_JOIN_HELPER(X, Y) X ## _ ## Y
 #define MINIFI_PRIVATE_JOIN(X, Y) MINIFI_PRIVATE_JOIN_HELPER(X, Y)
 
-#define MINIFI_API_MAJOR_VERSION 0
-#define MINIFI_API_MINOR_VERSION 1
-#define MINIFI_API_PATCH_VERSION 0
-#define MINIFI_API_VERSION MINIFI_PRIVATE_STRINGIFY(MINIFI_API_MAJOR_VERSION) 
"." MINIFI_PRIVATE_STRINGIFY(MINIFI_API_MINOR_VERSION) "." 
MINIFI_PRIVATE_STRINGIFY(MINIFI_API_PATCH_VERSION)
-
 #define MINIFI_NULL nullptr
 #define MINIFI_OWNED
 
@@ -46,6 +41,10 @@ extern "C" {
 #define MINIFI_CREATE_EXTENSION_FN MinifiCreateExtension
 #endif
 
+enum : uint32_t {
+  MINIFI_API_VERSION = 1
+};
+
 typedef bool MinifiBool;
 
 typedef enum MinifiIoStatus : int64_t {
@@ -221,7 +220,7 @@ typedef struct MinifiExtensionCreateInfo {
   const MinifiControllerServiceClassDefinition* controller_services_ptr;
 } MinifiExtensionCreateInfo;
 
-MinifiExtension* MINIFI_CREATE_EXTENSION_FN(const MinifiExtensionCreateInfo* 
create_info);
+MinifiStatus MINIFI_CREATE_EXTENSION_FN(MinifiExtension* extension, const 
MinifiExtensionCreateInfo* create_info);
 
 MINIFI_OWNED MinifiPublishedMetrics* MinifiPublishedMetricsCreate(size_t 
count, const MinifiStringView* metric_names, const double* metric_values);
 


Reply via email to