Skip to content

MSVC error C2026: string too big #166

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
gibki opened this issue May 2, 2025 · 2 comments · May be fixed by #167
Open

MSVC error C2026: string too big #166

gibki opened this issue May 2, 2025 · 2 comments · May be fixed by #167

Comments

@gibki
Copy link

gibki commented May 2, 2025

I have a huge enum (6000+ options) in my cdef. The generated C code for the array of _cffi_enum_s, field enumerators thus contains a humongous string which trips MSVC.

Huge generated strings need to be split. As a workaround I resorted to having typedef ... MyEnum; in the cdef, but now I don't have MyEnum's fields on my imported lib object.

@arigo
Copy link
Contributor

arigo commented May 2, 2025

@nitzmahone Here is a patch to fix the problem. As usual, I'm not used to github enough to make a pull request without spending a lot more time than I spent on this patch.

commit 020651d929f8f28b5e4a264c91f5302908295868
Author: Armin Rigo <[email protected]>
Date:   Fri May 2 17:53:58 2025 +0200

    split a big generated C string into multiple pieces, for MSVC

diff --git a/src/cffi/recompiler.py b/src/cffi/recompiler.py
index 7734a348..3183a4e7 100644
--- a/src/cffi/recompiler.py
+++ b/src/cffi/recompiler.py
@@ -93,9 +93,18 @@ class EnumExpr:
         self.allenums = allenums
 
     def as_c_expr(self):
-        return ('  { "%s", %d, _cffi_prim_int(%s, %s),\n'
-                '    "%s" },' % (self.name, self.type_index,
-                                 self.size, self.signed, self.allenums))
+        lines = ['  { "%s", %d, _cffi_prim_int(%s, %s),' % (self.name, self.type_index,
+                                                            self.size, self.signed,)]
+        pending = 0
+        while len(self.allenums) > pending + 110:
+            j = self.allenums.find(',', pending + 100)
+            if j < 0:
+                break
+            j += 1
+            lines.append('    "%s"' % (self.allenums[pending:j],))
+            pending = j
+        lines.append('    "%s" },' % (self.allenums[pending:],))
+        return '\n'.join(lines)
 
     def as_python_expr(self):
         prim_index = {
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
index f36512a3..fa7fec22 100644
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -2575,3 +2575,22 @@ def test_convert_api_mode_builtin_function_to_cdata():
     my_array_2 = ffi.new("void *[]", [lib.add1, lib.add2])
     assert ffi.cast("struct s(*)(struct s)", my_array_2[1])(s).x == 302
     assert ffi.typeof(lib.add1) == ffi.typeof("struct s(*)(struct s)")
+
+def test_large_enum():
+    ffi = FFI()
+    biglist = ['nn%d' % i for i in range(6000)]
+    ffi.cdef(
+        """enum foo_s { %s };""" % ','.join(biglist))
+    lib = verify(ffi, "test_large_enum", """
+        enum foo_s { %s };""" % ','.join(biglist))
+    assert lib.nn0 == 0
+    assert lib.nn1234 == 1234
+    assert lib.nn5999 == 5999
+    e = ffi.typeof("enum foo_s")
+    elements = {}
+    relements = {}
+    for i in range(6000):
+        elements[i] = biglist[i]
+        relements[biglist[i]] = i
+    assert e.elements == elements
+    assert e.relements == relements

@mattip mattip linked a pull request May 4, 2025 that will close this issue
@mattip
Copy link
Contributor

mattip commented May 4, 2025

Applied the patch in #167

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants