bytedeco / javacpp

The missing bridge between Java and native C++
Other
4.43k stars 576 forks source link

LNK2001: Unresolved external, issue with namespace? #721

Closed benshiffman closed 9 months ago

benshiffman commented 9 months ago

I'm getting a strange linker error (LNK2001, LNK1120) that I haven't been able to resolve with InfoMapping (javaNames, pointerTypes). I'm almost sure it has something to do with namespace discrepancies. Is there a way to remedy this without modifying the c/c++ source code? Any guidance would be greatly appreciated.

Linker error:

   Creating library jnilibname.lib and object jnilibname.exp
jnilibname.obj : error LNK2001: unresolved external symbol "public: void __thiscall LIBNAME::LibnameCppWrapper::libname_function(void)" (?libname_function@LibnameCppWrapper@LIBNAME@@QAEXXZ)

This is the code I deem to be relevant from my configuration and library files. I've replaced all instance of the name of my library with appropriate capitalizations of libname/Libname/LIBNAME for privacy. Hopefully the differences are clear.   My config class:

package org.bytedeco.libname.presets;

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;
import org.bytedeco.javacpp.tools.*;

@Properties(
        value = @Platform(
                include = {
                        "mlifc.h",
                },
                preload = {"libname"},
                link = {
                        "libname-static",
                },
                define = {"_CRT_SECURE_NO_WARNINGS"}
        ),
        target = "org.bytedeco.libname",
        global = "org.bytedeco.libname.global.libname"
)
public class libname implements InfoMapper
{
    static
    {
        Loader.checkVersion("org.bytedeco", "libname");
    }

    public void map(InfoMap infoMap)
    {
        infoMap.put(new Info("LIBNAME::LibNameCppWrapper::libname_function").javaNames("libname_function"));
    }
}

Included header mlifc.h:

#ifndef MLIFC_H
#define MLIFC_H

#include <string>
#include <vector>

extern "C" {
#include "libLibname.h"
}

namespace LIBNAME {

    struct LibnameCppWrapper {

    //other irrelevent members here

    public:
        void libname_function();
    };

}

#endif

CPP file mlifc.cpp

#include "mlifc.h"

#include <iostream>
#include <math.h>

using namespace std;

void LIBNAME::LibnameCppWrapper::libname_function() {
//function contents which I believe to be irrelevant
}
saudet commented 9 months ago

That just means that function isn't defined and/or exported. You can simply skip those because they are typically not meant for end users.

benshiffman commented 9 months ago

Feeling silly for skipping over the skip function. Built with no issues. Thank you!

benshiffman commented 9 months ago

Upon further review, I think skip() may not be what I need here. I assumed it would skip the processing of the extended namespace version of the function and pay attention to only the version in the header. I need to explicitly call the function where I've implemented the library. Is there a way to tell the parser/builder to be aware of the namespace difference?

saudet commented 9 months ago

The sample code above only has one function. If you have multiple functions and something isn't working for some reason, please provide an example of that. I can't fix what isn't broken!

benshiffman commented 9 months ago

Sorry for the confusion. I need to call libname_function() but skipping it using infoMap.put(new Info("LIBNAME::LibnameCppWrapper::libname_function").skip()) causes it not to be in the generated class. I'm looking to circumvent the unresolved external symbol error without skipping the function wrapping entirely.

saudet commented 9 months ago

Like I said, that's a problem with your native library, not JavaCPP. You'll need to fix your library and export that function.

benshiffman commented 9 months ago

Update: I'm beyond confused as to what caused this, but somehow mingw64 was using the x86 MSVC compiler, not the x64 version, which is what my library was compiled with. After I started a fresh instance and verified that running "cl" was showing x64 everything built correctly, no skip() needed.