Working type casters for wide strings and wide characters
diff --git a/README.md b/README.md
index 802d4eb..85172cc 100644
--- a/README.md
+++ b/README.md
@@ -92,6 +92,7 @@
 Jonas Adler,
 Sylvain Corlay,
 Axel Huebl,
+@hulucc,
 Johan Mabille,
 Tomasz Miąsko, and
 Ben Pritchard.
diff --git a/docs/basics.rst b/docs/basics.rst
index 53a325e..cb8962c 100644
--- a/docs/basics.rst
+++ b/docs/basics.rst
@@ -241,10 +241,14 @@
 +----------------------------+--------------------------+-----------------------+
 | char                       | Character literal        | pybind11/pybind11.h   |
 +----------------------------+--------------------------+-----------------------+
+| wchar_t                    | Wide character literal   | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
 | const char *               | UTF-8 string literal     | pybind11/pybind11.h   |
 +----------------------------+--------------------------+-----------------------+
 | std::string                | STL dynamic UTF-8 string | pybind11/pybind11.h   |
 +----------------------------+--------------------------+-----------------------+
+| std::wstring               | STL dynamic wide string  | pybind11/pybind11.h   |
++----------------------------+--------------------------+-----------------------+
 | std::pair<T1, T2>          | Pair of two custom types | pybind11/pybind11.h   |
 +----------------------------+--------------------------+-----------------------+
 | std::tuple<....>           | Arbitrary tuple of types | pybind11/pybind11.h   |
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 3aae65b..00fd2ea 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -5,8 +5,7 @@
 
 1.4 (not yet released)
 --------------------------
-TBD
-
+* Transparent type conversion for ``std::wstring`` and ``wchar_t``
 
 1.3 (March 8, 2016)
 --------------------------
diff --git a/example/example2.cpp b/example/example2.cpp
index 3282a85..b137f99 100644
--- a/example/example2.cpp
+++ b/example/example2.cpp
@@ -60,9 +60,9 @@
     }
 
     /* C++ STL data types are automatically casted */
-    std::vector<std::string> get_list_2() {
-        std::vector<std::string> list;
-        list.push_back("value");
+    std::vector<std::wstring> get_list_2() {
+        std::vector<std::wstring> list;
+        list.push_back(L"value");
         return list;
     }
 
@@ -103,10 +103,10 @@
     }
 
     /* STL data types (such as vectors) are automatically casted from Python */
-    void print_list_2(std::vector<std::string> &list) {
+    void print_list_2(std::vector<std::wstring> &list) {
         int index = 0;
         for (auto item : list)
-            std::cout << "list item " << index++ << ": " << item << std::endl;
+            std::wcout << L"list item " << index++ << L": " << item << std::endl;
     }
 
     /* pybind automatically translates between C++11 and Python tuples */
diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h
index 38918ee..f22b670 100644
--- a/include/pybind11/cast.h
+++ b/include/pybind11/cast.h
@@ -349,22 +349,45 @@
     PYBIND11_TYPE_CASTER(std::string, _(PYBIND11_STRING_NAME));
 };
 
-template <> class type_caster<char> {
+template <> class type_caster<std::wstring> {
 public:
-    bool load(handle src, bool) {
-        object temp;
-        handle load_src = src;
-        if (PyUnicode_Check(load_src.ptr())) {
-            temp = object(PyUnicode_AsUTF8String(load_src.ptr()), false);
-            if (!temp) { PyErr_Clear(); return false; }  // UnicodeEncodeError
-            load_src = temp;
+	bool load(handle src, bool) {
+		object temp;
+		handle load_src = src;
+		if (!PyUnicode_Check(load_src.ptr())) {
+			temp = object(PyUnicode_FromObject(load_src.ptr()), false);
+			if (!temp) { PyErr_Clear(); return false; }
+			load_src = temp;
+		}
+        wchar_t *buffer = nullptr;
+        ssize_t length = -1;
+#if PY_MAJOR_VERSION >= 3
+        buffer = PyUnicode_AsWideCharString(load_src.ptr(), &length);
+#else
+        temp = object(
+            sizeof(wchar_t) == sizeof(short)
+                ? PyUnicode_AsUTF16String(load_src.ptr())
+                : PyUnicode_AsUTF32String(load_src.ptr()), false);
+        if (temp) {
+            int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), (char **) &buffer, &length);
+            if (err == -1) { buffer = nullptr; }  // TypeError
+            length = length / sizeof(wchar_t) - 1; ++buffer; // Skip BOM
         }
-        const char *ptr = PYBIND11_BYTES_AS_STRING(load_src.ptr());
-        if (!ptr) { PyErr_Clear(); return false; }  // TypeError
-        value = std::string(ptr);
-        return true;
-    }
+#endif
+        if (!buffer) { PyErr_Clear(); return false; }
+		value = std::wstring(buffer, length);
+		return true;
+	}
 
+	static handle cast(const std::wstring &src, return_value_policy /* policy */, handle /* parent */) {
+		return PyUnicode_FromWideChar(src.c_str(), src.length());
+	}
+
+	PYBIND11_TYPE_CASTER(std::wstring, _(PYBIND11_STRING_NAME));
+};
+
+template <> class type_caster<char> : public type_caster<std::string> {
+public:
     static handle cast(const char *src, return_value_policy /* policy */, handle /* parent */) {
         return PyUnicode_FromString(src);
     }
@@ -382,6 +405,25 @@
     std::string value;
 };
 
+template <> class type_caster<wchar_t> : public type_caster<std::wstring> {
+public:
+	static handle cast(const wchar_t *src, return_value_policy /* policy */, handle /* parent */) {
+		return PyUnicode_FromWideChar(src, wcslen(src));
+	}
+
+	static handle cast(wchar_t src, return_value_policy /* policy */, handle /* parent */) {
+		wchar_t wstr[2] = { src, L'\0' };
+		return PyUnicode_FromWideChar(wstr, 1);
+	}
+
+	operator wchar_t*() { return (wchar_t *)value.c_str(); }
+	operator wchar_t() { if (value.length() > 0) return value[0]; else return L'\0'; }
+
+	static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); }
+protected:
+	std::wstring value;
+};
+
 template <typename T1, typename T2> class type_caster<std::pair<T1, T2>> {
     typedef std::pair<T1, T2> type;
 public: