Skip to content

Commit 007c79a

Browse files
committed
Initial commit. Adds the main classes and types which will feature in the library.
1 parent 5eeca32 commit 007c79a

File tree

8 files changed

+468
-3
lines changed

8 files changed

+468
-3
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2016 Mitch
3+
Copyright (c) 2016 Mitchell Dowd
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,18 @@
1-
# jnipp
2-
C++ wrapper for the Java Native Interface
1+
Java Native Interface for C++
2+
=============================
3+
4+
## Overview
5+
6+
JNIPP is just a C++ wrapper for the standard Java Native Interface (JNI). It
7+
tries to take some of the long-winded annoyance out of integrating your Java
8+
and C++ code.
9+
10+
## Requirements
11+
12+
To compile you will need:
13+
- A C++11 compatible compiler
14+
- An installation of the Java Development Kit (JDK)
15+
16+
To compile in Visual Studio, you will need your `JAVA_HOME` environment variable
17+
correctly set to the JDK installation directory.
18+

jnipp.cpp

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// External Dependencies
2+
#include <jni.h>
3+
4+
// Local Dependencies
5+
#include "jnipp.h"
6+
7+
namespace jni
8+
{
9+
// Static Variables
10+
static JavaVM* javaVm = nullptr;
11+
12+
/**
13+
Maintains the lifecycle of a JNIEnv.
14+
*/
15+
class ScopedEnv final
16+
{
17+
public:
18+
ScopedEnv() : _vm(nullptr), _env(nullptr), _attached(false) {}
19+
~ScopedEnv();
20+
21+
void init(JavaVM* vm);
22+
JNIEnv* get() const { return _env; }
23+
24+
private:
25+
// Instance Variables
26+
JavaVM* _vm;
27+
JNIEnv* _env;
28+
bool _attached; ///< Manually attached, as opposed to already attached.
29+
};
30+
31+
ScopedEnv::~ScopedEnv()
32+
{
33+
if (_vm && _attached)
34+
_vm->DetachCurrentThread();
35+
}
36+
37+
void ScopedEnv::init(JavaVM* vm)
38+
{
39+
if (_env != nullptr)
40+
return;
41+
42+
if (vm == nullptr)
43+
throw InitializationException("JNI not initialized");
44+
45+
if (vm->GetEnv((void**) &_env, JNI_VERSION_1_4) != JNI_OK)
46+
{
47+
if (vm->AttachCurrentThread((void**) &_env, nullptr) != 0)
48+
throw InitializationException("Could not attach JNI to thread");
49+
50+
_attached = true;
51+
}
52+
}
53+
54+
/*
55+
Helper Functions
56+
*/
57+
58+
static JNIEnv* env()
59+
{
60+
static thread_local ScopedEnv env;
61+
62+
if (env.get() == nullptr)
63+
env.init(javaVm);
64+
65+
return env.get();
66+
}
67+
68+
/*
69+
Stand-alone Function Impelementations
70+
*/
71+
72+
void init(JNIEnv* env)
73+
{
74+
if (javaVm != nullptr)
75+
return;
76+
77+
if (env->GetJavaVM(&javaVm) != 0)
78+
throw InitializationException("Could not acquire Java VM");
79+
}
80+
81+
/*
82+
Object Implementation
83+
*/
84+
85+
Object::Object(jobject ref, int scopeFlags) : _handle(ref), _class(nullptr), _isGlobal((scopeFlags & Temporary) == 0)
86+
{
87+
if (!_isGlobal)
88+
return;
89+
90+
JNIEnv* env = jni::env();
91+
92+
_handle = env->NewGlobalRef(ref);
93+
94+
if (scopeFlags & DeleteLocalInput)
95+
env->DeleteLocalRef(ref);
96+
}
97+
98+
Object::~Object()
99+
{
100+
JNIEnv* env = jni::env();
101+
102+
if (_isGlobal)
103+
env->DeleteGlobalRef(_handle);
104+
105+
if (_class != nullptr)
106+
env->DeleteGlobalRef(_class);
107+
}
108+
109+
/*
110+
Class Implementation
111+
*/
112+
113+
Class::Class(jclass ref, int scopeFlags) : Object(ref, scopeFlags)
114+
{
115+
}
116+
}
117+

jnipp.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#ifndef _JNIPP_H_
2+
#define _JNIPP_H_ 1
3+
4+
// Local Dependencies
5+
#include "types.h"
6+
7+
namespace jni
8+
{
9+
/**
10+
Initialises the Java Native Interface with the given JNIEnv handle, which
11+
gets passed into a native function which is called from Java. This only
12+
needs to be done once per process - further calls are no-ops. Note that
13+
this does _not_ start a new Java Virtual Machine, it simply attaches to
14+
an existing one.
15+
\param env A JNI environment handle.
16+
*/
17+
void init(JNIEnv* env);
18+
19+
/**
20+
Object corresponds with a `java.lang.Object` instance. With an Object,
21+
you can then call Java methods, and access fields on the Object. To
22+
instantiate an Object of a given class, use the `Class` class.
23+
*/
24+
class Object
25+
{
26+
public:
27+
/** Flags which can be passed to the Object constructor. */
28+
enum ScopeFlags
29+
{
30+
Temporary = 1, ///< Temporary object. Do not create a global reference.
31+
DeleteLocalInput = 2 ///< The input reference is temporary and can be deleted.
32+
};
33+
34+
/**
35+
Creates an Object from a local JNI reference.
36+
\param ref The local JNI reference.
37+
\param scopeFlags Bitmask of ScopeFlags values.
38+
*/
39+
Object(jobject ref, int scopeFlags = 0);
40+
41+
/**
42+
Destructor. Releases this reference on the Java Object so it can be
43+
picked up by the garbage collector.
44+
*/
45+
virtual ~Object();
46+
47+
private:
48+
// Instance Variables
49+
jobject _handle;
50+
mutable jclass _class;
51+
bool _isGlobal;
52+
};
53+
54+
/**
55+
Class corresponds with `java.lang.Class`, and allows you to instantiate
56+
Objects and get class members such as methods and fields.
57+
*/
58+
class Class final : public Object
59+
{
60+
public:
61+
/**
62+
Creates a Class object by JNI reference.
63+
\param ref The JNI class reference.
64+
\param scopeFlags Bitmask of Object::ScopeFlags.
65+
*/
66+
Class(jclass ref, int scopeFlags = 0);
67+
};
68+
69+
/**
70+
A Java method call threw an Exception.
71+
*/
72+
class InvokationException : public Exception
73+
{
74+
};
75+
76+
/**
77+
The Java Native Interface was not properly initialized.
78+
*/
79+
class InitializationException : public Exception
80+
{
81+
public:
82+
/**
83+
Constructor with an error message.
84+
\param msg Message to pass to the Exception.
85+
*/
86+
InitializationException(const char* msg) : Exception(msg) {}
87+
};
88+
}
89+
90+
#endif // _JNIPP_H_
91+

jnipp.sln

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 14
4+
VisualStudioVersion = 14.0.25420.1
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jnipp", "jnipp.vcxproj", "{A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}"
7+
EndProject
8+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Files", "Solution Files", "{5A4C5782-6F86-4413-9E19-3F6539DCD835}"
9+
ProjectSection(SolutionItems) = preProject
10+
LICENSE = LICENSE
11+
README.md = README.md
12+
EndProjectSection
13+
EndProject
14+
Global
15+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
16+
Debug|x64 = Debug|x64
17+
Debug|x86 = Debug|x86
18+
Release|x64 = Release|x64
19+
Release|x86 = Release|x86
20+
EndGlobalSection
21+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
22+
{A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Debug|x64.ActiveCfg = Debug|x64
23+
{A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Debug|x64.Build.0 = Debug|x64
24+
{A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Debug|x86.ActiveCfg = Debug|Win32
25+
{A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Debug|x86.Build.0 = Debug|Win32
26+
{A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Release|x64.ActiveCfg = Release|x64
27+
{A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Release|x64.Build.0 = Release|x64
28+
{A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Release|x86.ActiveCfg = Release|Win32
29+
{A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Release|x86.Build.0 = Release|Win32
30+
EndGlobalSection
31+
GlobalSection(SolutionProperties) = preSolution
32+
HideSolutionNode = FALSE
33+
EndGlobalSection
34+
EndGlobal

0 commit comments

Comments
 (0)